@sentry/node 8.0.0-beta.1 → 8.0.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. package/cjs/index.js +159 -22
  2. package/cjs/index.js.map +1 -1
  3. package/esm/index.js +160 -24
  4. package/esm/index.js.map +1 -1
  5. package/esm/integrations/anr/worker-script.js +2 -2
  6. package/esm/integrations/local-variables/worker-script.js +2 -0
  7. package/package.json +14 -14
  8. package/types/index.d.ts +1 -1
  9. package/types/index.d.ts.map +1 -1
  10. package/types/integrations/anr/index.d.ts +1 -0
  11. package/types/integrations/anr/index.d.ts.map +1 -1
  12. package/types/integrations/local-variables/common.d.ts +12 -0
  13. package/types/integrations/local-variables/common.d.ts.map +1 -1
  14. package/types/integrations/local-variables/index.d.ts +3 -1
  15. package/types/integrations/local-variables/index.d.ts.map +1 -1
  16. package/types/integrations/local-variables/local-variables-async.d.ts +7 -0
  17. package/types/integrations/local-variables/local-variables-async.d.ts.map +1 -0
  18. package/types/integrations/local-variables/worker.d.ts +2 -0
  19. package/types/integrations/local-variables/worker.d.ts.map +1 -0
  20. package/types/sdk/initOtel.d.ts.map +1 -1
  21. package/types-ts3.8/index.d.ts +1 -1
  22. package/types-ts3.8/integrations/anr/index.d.ts +1 -0
  23. package/types-ts3.8/integrations/local-variables/common.d.ts +12 -0
  24. package/types-ts3.8/integrations/local-variables/index.d.ts +3 -1
  25. package/types-ts3.8/integrations/local-variables/local-variables-async.d.ts +7 -0
  26. package/types-ts3.8/integrations/local-variables/worker.d.ts +2 -0
  27. package/types/integrations/anr/worker-script.d.ts +0 -2
  28. package/types/integrations/anr/worker-script.d.ts.map +0 -1
  29. package/types-ts3.8/integrations/anr/worker-script.d.ts +0 -2
package/esm/index.js CHANGED
@@ -5,7 +5,7 @@ import { HttpInstrumentation } from '@opentelemetry/instrumentation-http';
5
5
  import { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, defineIntegration, isSentryRequestUrl, getCapturedScopesOnSpan, getIsolationScope, getCurrentScope, setCapturedScopesOnSpan, spanToJSON, addBreadcrumb, getClient as getClient$1, captureException, getGlobalScope, mergeScopeData, getDefaultIsolationScope, SDK_VERSION, getActiveSpan, getRootSpan, SPAN_STATUS_ERROR, createTransport, suppressTracing, ServerRuntimeClient, applySdkMetadata, inboundFiltersIntegration, functionToStringIntegration, linkedErrorsIntegration, requestDataIntegration, hasTracingEnabled, getIntegrationsToSetup, startSession, endSession, withMonitor } from '@sentry/core';
6
6
  export { SDK_VERSION, SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, Scope, addBreadcrumb, addEventProcessor, addIntegration, captureCheckIn, captureConsoleIntegration, captureEvent, captureException, captureMessage, captureSession, close, createTransport, debugIntegration, dedupeIntegration, endSession, extraErrorDataIntegration, flush, functionToStringIntegration, getActiveSpan, getClient, getCurrentHub, getCurrentScope, getGlobalScope, getIsolationScope, getRootSpan, getSpanDescendants, getSpanStatusFromHttpCode, inboundFiltersIntegration, isInitialized, linkedErrorsIntegration, metricsDefault as metrics, parameterize, requestDataIntegration, rewriteFramesIntegration, sessionTimingIntegration, setContext, setCurrentClient, setExtra, setExtras, setHttpStatus, setMeasurement, setTag, setTags, setUser, spanToJSON, spanToTraceHeader, startInactiveSpan, startSession, startSpan, startSpanManual, trpcMiddleware, withActiveSpan, withIsolationScope, withMonitor, withScope } from '@sentry/core';
7
7
  import { getScopesFromContext, getClient, getSpanKind, getRequestSpanData, wrapContextManagerClass, setupEventContextTrace, SentrySampler, SentrySpanProcessor, SentryPropagator, setOpenTelemetryContextAsyncContextStrategy, openTelemetrySetupCheck } from '@sentry/opentelemetry';
8
- export { continueTrace } from '@sentry/opentelemetry';
8
+ export { continueTrace, setOpenTelemetryContextAsyncContextStrategy as setNodeAsyncContextStrategy } from '@sentry/opentelemetry';
9
9
  import { stripUrlQueryAndFragment, parseSemver, logger, addConsoleInstrumentationHandler, severityLevelFromString, LRUMap, addContextToFrame, consoleSandbox, GLOBAL_OBJ, serializeEnvelope, dirname as dirname$1, createStackParser, nodeStackLineParser, dropUndefinedKeys, stackParserFromStackParserOptions, propagationContextFromHeaders } from '@sentry/utils';
10
10
  export { DEFAULT_USER_INCLUDES, addRequestDataToEvent, extractRequestData } from '@sentry/utils';
11
11
  import * as util from 'util';
@@ -14,9 +14,9 @@ import { execFile } from 'child_process';
14
14
  import { readFile, readdir, promises, existsSync, readFileSync } from 'fs';
15
15
  import * as os from 'os';
16
16
  import { join, dirname, posix, sep } from 'path';
17
+ import { Worker } from 'worker_threads';
17
18
  import * as inspector from 'inspector';
18
19
  import { Session } from 'inspector';
19
- import { Worker } from 'worker_threads';
20
20
  import { ExpressInstrumentation } from '@opentelemetry/instrumentation-express';
21
21
  import { FastifyInstrumentation } from '@opentelemetry/instrumentation-fastify';
22
22
  import { GraphQLInstrumentation } from '@opentelemetry/instrumentation-graphql';
@@ -29,7 +29,7 @@ import { PgInstrumentation } from '@opentelemetry/instrumentation-pg';
29
29
  import * as prismaInstrumentation from '@prisma/instrumentation';
30
30
  import { HapiInstrumentation } from '@opentelemetry/instrumentation-hapi';
31
31
  import { KoaInstrumentation } from '@opentelemetry/instrumentation-koa';
32
- import { SemanticAttributes, SemanticResourceAttributes } from '@opentelemetry/semantic-conventions';
32
+ import { SEMATTRS_HTTP_ROUTE, SEMRESATTRS_SERVICE_NAME, SEMRESATTRS_SERVICE_NAMESPACE, SEMRESATTRS_SERVICE_VERSION } from '@opentelemetry/semantic-conventions';
33
33
  import * as http from 'http';
34
34
  import * as http$1 from 'node:http';
35
35
  import * as https from 'node:https';
@@ -71,7 +71,7 @@ function getRequestUrl(requestOptions) {
71
71
  return `${protocol}//${hostname}${port}${path}`;
72
72
  }
73
73
 
74
- function _optionalChain$b(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
74
+ function _optionalChain$c(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
75
75
 
76
76
  const _httpIntegration = ((options = {}) => {
77
77
  const _breadcrumbs = typeof options.breadcrumbs === 'undefined' ? true : options.breadcrumbs;
@@ -104,7 +104,7 @@ const _httpIntegration = ((options = {}) => {
104
104
  ignoreIncomingRequestHook: request => {
105
105
  const url = getRequestUrl(request);
106
106
 
107
- const method = _optionalChain$b([request, 'access', _ => _.method, 'optionalAccess', _2 => _2.toUpperCase, 'call', _3 => _3()]);
107
+ const method = _optionalChain$c([request, 'access', _ => _.method, 'optionalAccess', _2 => _2.toUpperCase, 'call', _3 => _3()]);
108
108
  // We do not capture OPTIONS/HEAD requests as transactions
109
109
  if (method === 'OPTIONS' || method === 'HEAD') {
110
110
  return true;
@@ -335,7 +335,7 @@ const _consoleIntegration = (() => {
335
335
  */
336
336
  const consoleIntegration = defineIntegration(_consoleIntegration);
337
337
 
338
- function _optionalChain$a(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
338
+ function _optionalChain$b(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
339
339
  const readFileAsync$1 = promisify(readFile);
340
340
  const readDirAsync = promisify(readdir);
341
341
 
@@ -363,11 +363,11 @@ const _nodeContextIntegration = ((options = {}) => {
363
363
 
364
364
  event.contexts = {
365
365
  ...event.contexts,
366
- app: { ...updatedContext.app, ..._optionalChain$a([event, 'access', _ => _.contexts, 'optionalAccess', _2 => _2.app]) },
367
- os: { ...updatedContext.os, ..._optionalChain$a([event, 'access', _3 => _3.contexts, 'optionalAccess', _4 => _4.os]) },
368
- device: { ...updatedContext.device, ..._optionalChain$a([event, 'access', _5 => _5.contexts, 'optionalAccess', _6 => _6.device]) },
369
- culture: { ...updatedContext.culture, ..._optionalChain$a([event, 'access', _7 => _7.contexts, 'optionalAccess', _8 => _8.culture]) },
370
- cloud_resource: { ...updatedContext.cloud_resource, ..._optionalChain$a([event, 'access', _9 => _9.contexts, 'optionalAccess', _10 => _10.cloud_resource]) },
366
+ app: { ...updatedContext.app, ..._optionalChain$b([event, 'access', _ => _.contexts, 'optionalAccess', _2 => _2.app]) },
367
+ os: { ...updatedContext.os, ..._optionalChain$b([event, 'access', _3 => _3.contexts, 'optionalAccess', _4 => _4.os]) },
368
+ device: { ...updatedContext.device, ..._optionalChain$b([event, 'access', _5 => _5.contexts, 'optionalAccess', _6 => _6.device]) },
369
+ culture: { ...updatedContext.culture, ..._optionalChain$b([event, 'access', _7 => _7.contexts, 'optionalAccess', _8 => _8.culture]) },
370
+ cloud_resource: { ...updatedContext.cloud_resource, ..._optionalChain$b([event, 'access', _9 => _9.contexts, 'optionalAccess', _10 => _10.cloud_resource]) },
371
371
  };
372
372
 
373
373
  return event;
@@ -422,11 +422,11 @@ const nodeContextIntegration = defineIntegration(_nodeContextIntegration);
422
422
  */
423
423
  function _updateContext(contexts) {
424
424
  // Only update properties if they exist
425
- if (_optionalChain$a([contexts, 'optionalAccess', _11 => _11.app, 'optionalAccess', _12 => _12.app_memory])) {
425
+ if (_optionalChain$b([contexts, 'optionalAccess', _11 => _11.app, 'optionalAccess', _12 => _12.app_memory])) {
426
426
  contexts.app.app_memory = process.memoryUsage().rss;
427
427
  }
428
428
 
429
- if (_optionalChain$a([contexts, 'optionalAccess', _13 => _13.device, 'optionalAccess', _14 => _14.free_memory])) {
429
+ if (_optionalChain$b([contexts, 'optionalAccess', _13 => _13.device, 'optionalAccess', _14 => _14.free_memory])) {
430
430
  contexts.device.free_memory = os.freemem();
431
431
  }
432
432
 
@@ -753,7 +753,7 @@ function getCloudResourceContext() {
753
753
  }
754
754
  }
755
755
 
756
- function _optionalChain$9(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
756
+ function _optionalChain$a(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
757
757
  const FILE_CONTENT_CACHE = new LRUMap(100);
758
758
  const DEFAULT_LINES_OF_CONTEXT = 7;
759
759
  const INTEGRATION_NAME$6 = 'ContextLines';
@@ -783,9 +783,9 @@ async function addSourceContext(event, contextLines) {
783
783
  const enqueuedReadSourceFileTasks = {};
784
784
  const readSourceFileTasks = [];
785
785
 
786
- if (contextLines > 0 && _optionalChain$9([event, 'access', _2 => _2.exception, 'optionalAccess', _3 => _3.values])) {
786
+ if (contextLines > 0 && _optionalChain$a([event, 'access', _2 => _2.exception, 'optionalAccess', _3 => _3.values])) {
787
787
  for (const exception of event.exception.values) {
788
- if (!_optionalChain$9([exception, 'access', _4 => _4.stacktrace, 'optionalAccess', _5 => _5.frames])) {
788
+ if (!_optionalChain$a([exception, 'access', _4 => _4.stacktrace, 'optionalAccess', _5 => _5.frames])) {
789
789
  continue;
790
790
  }
791
791
 
@@ -812,7 +812,7 @@ async function addSourceContext(event, contextLines) {
812
812
 
813
813
  // Perform the same loop as above, but this time we can assume all files are in the cache
814
814
  // and attempt to add source context to frames.
815
- if (contextLines > 0 && _optionalChain$9([event, 'access', _6 => _6.exception, 'optionalAccess', _7 => _7.values])) {
815
+ if (contextLines > 0 && _optionalChain$a([event, 'access', _6 => _6.exception, 'optionalAccess', _7 => _7.values])) {
816
816
  for (const exception of event.exception.values) {
817
817
  if (exception.stacktrace && exception.stacktrace.frames) {
818
818
  await addSourceContextToFrames(exception.stacktrace.frames, contextLines);
@@ -957,6 +957,140 @@ function hashFromStack(stackParser, stack) {
957
957
  return hashFrames(stackParser(stack, 1));
958
958
  }
959
959
 
960
+ function _optionalChain$9(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
961
+ // This string is a placeholder that gets overwritten with the worker code.
962
+ const base64WorkerScript$1 = 'LyohIEBzZW50cnkvbm9kZSA4LjAuMC1iZXRhLjIgKGYyMTViYWIpIHwgaHR0cHM6Ly9naXRodWIuY29tL2dldHNlbnRyeS9zZW50cnktamF2YXNjcmlwdCAqLwppbXBvcnR7U2Vzc2lvbiBhcyBlfWZyb20ibm9kZTppbnNwZWN0b3IvcHJvbWlzZXMiO2ltcG9ydHt3b3JrZXJEYXRhIGFzIG4scGFyZW50UG9ydCBhcyB0fWZyb20id29ya2VyX3RocmVhZHMiO2ltcG9ydHtwb3NpeCBhcyBvLHNlcCBhcyByfWZyb20icGF0aCI7Y29uc3QgaT01MCxzPSI/IixjPS9cKGVycm9yOiAoLiopXCkvLGE9L2NhcHR1cmVNZXNzYWdlfGNhcHR1cmVFeGNlcHRpb24vO2NvbnN0IHU9L14oXFMrOlxcfFwvPykoW1xzXFNdKj8pKCg/OlwuezEsMn18W14vXFxdKz98KShcLlteLi9cXF0qfCkpKD86Wy9cXF0qKSQvO2Z1bmN0aW9uIGYoZSl7Y29uc3Qgbj1mdW5jdGlvbihlKXtjb25zdCBuPWUubGVuZ3RoPjEwMjQ/YDx0cnVuY2F0ZWQ+JHtlLnNsaWNlKC0xMDI0KX1gOmUsdD11LmV4ZWMobik7cmV0dXJuIHQ/dC5zbGljZSgxKTpbXX0oZSksdD1uWzBdO2xldCBvPW5bMV07cmV0dXJuIHR8fG8/KG8mJihvPW8uc2xpY2UoMCxvLmxlbmd0aC0xKSksdCtvKToiLiJ9ZnVuY3Rpb24gbChlLG49ITEpe3JldHVybiEobnx8ZSYmIWUuc3RhcnRzV2l0aCgiLyIpJiYhZS5tYXRjaCgvXltBLVpdOi8pJiYhZS5zdGFydHNXaXRoKCIuIikmJiFlLm1hdGNoKC9eW2EtekEtWl0oW2EtekEtWjAtOS5cLStdKSo6XC9cLy8pKSYmdm9pZCAwIT09ZSYmIWUuaW5jbHVkZXMoIm5vZGVfbW9kdWxlcy8iKX1mdW5jdGlvbiBkKGUpe2NvbnN0IG49L15ccypbLV17NCx9JC8sdD0vYXQgKD86YXN5bmMgKT8oPzooLis/KVxzK1woKT8oPzooLispOihcZCspOihcZCspP3woW14pXSspKVwpPy87cmV0dXJuIG89Pntjb25zdCByPW8ubWF0Y2godCk7aWYocil7bGV0IG4sdCxvLGksYztpZihyWzFdKXtvPXJbMV07bGV0IGU9by5sYXN0SW5kZXhPZigiLiIpO2lmKCIuIj09PW9bZS0xXSYmZS0tLGU+MCl7bj1vLnNsaWNlKDAsZSksdD1vLnNsaWNlKGUrMSk7Y29uc3Qgcj1uLmluZGV4T2YoIi5Nb2R1bGUiKTtyPjAmJihvPW8uc2xpY2UocisxKSxuPW4uc2xpY2UoMCxyKSl9aT12b2lkIDB9dCYmKGk9bixjPXQpLCI8YW5vbnltb3VzPiI9PT10JiYoYz12b2lkIDAsbz12b2lkIDApLHZvaWQgMD09PW8mJihjPWN8fHMsbz1pP2Ake2l9LiR7Y31gOmMpO2xldCBhPXJbMl0mJnJbMl0uc3RhcnRzV2l0aCgiZmlsZTovLyIpP3JbMl0uc2xpY2UoNyk6clsyXTtjb25zdCB1PSJuYXRpdmUiPT09cls1XTtyZXR1cm4gYSYmYS5tYXRjaCgvXC9bQS1aXTovKSYmKGE9YS5zbGljZSgxKSksYXx8IXJbNV18fHV8fChhPXJbNV0pLHtmaWxlbmFtZTphLG1vZHVsZTplP2UoYSk6dm9pZCAwLGZ1bmN0aW9uOm8sbGluZW5vOnBhcnNlSW50KHJbM10sMTApfHx2b2lkIDAsY29sbm86cGFyc2VJbnQocls0XSwxMCl8fHZvaWQgMCxpbl9hcHA6bChhLHUpfX1pZihvLm1hdGNoKG4pKXJldHVybntmaWxlbmFtZTpvfX19ZnVuY3Rpb24gcChlKXtyZXR1cm4gZS5yZXBsYWNlKC9eW0EtWl06LywiIikucmVwbGFjZSgvXFwvZywiLyIpfWNvbnN0IGc9bixtPWZ1bmN0aW9uKC4uLmUpe2NvbnN0IG49ZS5zb3J0KCgoZSxuKT0+ZVswXS1uWzBdKSkubWFwKChlPT5lWzFdKSk7cmV0dXJuKGUsdD0wLG89MCk9Pntjb25zdCByPVtdLHU9ZS5zcGxpdCgiXG4iKTtmb3IobGV0IGU9dDtlPHUubGVuZ3RoO2UrKyl7Y29uc3QgdD11W2VdO2lmKHQubGVuZ3RoPjEwMjQpY29udGludWU7Y29uc3Qgcz1jLnRlc3QodCk/dC5yZXBsYWNlKGMsIiQxIik6dDtpZighcy5tYXRjaCgvXFMqRXJyb3I6IC8pKXtmb3IoY29uc3QgZSBvZiBuKXtjb25zdCBuPWUocyk7aWYobil7ci5wdXNoKG4pO2JyZWFrfX1pZihyLmxlbmd0aD49aStvKWJyZWFrfX1yZXR1cm4gZnVuY3Rpb24oZSl7aWYoIWUubGVuZ3RoKXJldHVybltdO2NvbnN0IG49QXJyYXkuZnJvbShlKTsvc2VudHJ5V3JhcHBlZC8udGVzdChuW24ubGVuZ3RoLTFdLmZ1bmN0aW9ufHwiIikmJm4ucG9wKCk7bi5yZXZlcnNlKCksYS50ZXN0KG5bbi5sZW5ndGgtMV0uZnVuY3Rpb258fCIiKSYmKG4ucG9wKCksYS50ZXN0KG5bbi5sZW5ndGgtMV0uZnVuY3Rpb258fCIiKSYmbi5wb3AoKSk7cmV0dXJuIG4uc2xpY2UoMCxpKS5tYXAoKGU9Pih7Li4uZSxmaWxlbmFtZTplLmZpbGVuYW1lfHxuW24ubGVuZ3RoLTFdLmZpbGVuYW1lLGZ1bmN0aW9uOmUuZnVuY3Rpb258fHN9KSkpfShyLnNsaWNlKG8pKX19KFs5MCxkKGZ1bmN0aW9uKGU9KHByb2Nlc3MuYXJndlsxXT9mKHByb2Nlc3MuYXJndlsxXSk6cHJvY2Vzcy5jd2QoKSksbj0iXFwiPT09cil7Y29uc3QgdD1uP3AoZSk6ZTtyZXR1cm4gZT0+e2lmKCFlKXJldHVybjtjb25zdCByPW4/cChlKTplO2xldHtkaXI6aSxiYXNlOnMsZXh0OmN9PW8ucGFyc2Uocik7Ii5qcyIhPT1jJiYiLm1qcyIhPT1jJiYiLmNqcyIhPT1jfHwocz1zLnNsaWNlKDAsLTEqYy5sZW5ndGgpKSxpfHwoaT0iLiIpO2NvbnN0IGE9aS5sYXN0SW5kZXhPZigiL25vZGVfbW9kdWxlcyIpO2lmKGE+LTEpcmV0dXJuYCR7aS5zbGljZShhKzE0KS5yZXBsYWNlKC9cLy9nLCIuIil9OiR7c31gO2lmKGkuc3RhcnRzV2l0aCh0KSl7bGV0IGU9aS5zbGljZSh0Lmxlbmd0aCsxKS5yZXBsYWNlKC9cLy9nLCIuIik7cmV0dXJuIGUmJihlKz0iOiIpLGUrPXMsZX1yZXR1cm4gc319KGcuYmFzZVBhdGgpKV0pO2Z1bmN0aW9uIGIoLi4uZSl7Zy5kZWJ1ZyYmY29uc29sZS5sb2coIltMb2NhbFZhcmlhYmxlcyBXb3JrZXJdIiwuLi5lKX1hc3luYyBmdW5jdGlvbiB2KGUsbix0LG8pe2NvbnN0IHI9YXdhaXQgZS5wb3N0KCJSdW50aW1lLmdldFByb3BlcnRpZXMiLHtvYmplY3RJZDpuLG93blByb3BlcnRpZXM6ITB9KTtvW3RdPXIucmVzdWx0LmZpbHRlcigoZT0+Imxlbmd0aCIhPT1lLm5hbWUmJiFpc05hTihwYXJzZUludChlLm5hbWUsMTApKSkpLnNvcnQoKChlLG4pPT5wYXJzZUludChlLm5hbWUsMTApLXBhcnNlSW50KG4ubmFtZSwxMCkpKS5tYXAoKGU9PmUudmFsdWU/LnZhbHVlKSl9YXN5bmMgZnVuY3Rpb24gJChlLG4sdCxvKXtjb25zdCByPWF3YWl0IGUucG9zdCgiUnVudGltZS5nZXRQcm9wZXJ0aWVzIix7b2JqZWN0SWQ6bixvd25Qcm9wZXJ0aWVzOiEwfSk7b1t0XT1yLnJlc3VsdC5tYXAoKGU9PltlLm5hbWUsZS52YWx1ZT8udmFsdWVdKSkucmVkdWNlKCgoZSxbbix0XSk9PihlW25dPXQsZSkpLHt9KX1mdW5jdGlvbiB3KGUsbil7ZS52YWx1ZSYmKCJ2YWx1ZSJpbiBlLnZhbHVlP3ZvaWQgMD09PWUudmFsdWUudmFsdWV8fG51bGw9PT1lLnZhbHVlLnZhbHVlP25bZS5uYW1lXT1gPCR7ZS52YWx1ZS52YWx1ZX0+YDpuW2UubmFtZV09ZS52YWx1ZS52YWx1ZToiZGVzY3JpcHRpb24iaW4gZS52YWx1ZSYmImZ1bmN0aW9uIiE9PWUudmFsdWUudHlwZT9uW2UubmFtZV09YDwke2UudmFsdWUuZGVzY3JpcHRpb259PmA6InVuZGVmaW5lZCI9PT1lLnZhbHVlLnR5cGUmJihuW2UubmFtZV09Ijx1bmRlZmluZWQ+IikpfWFzeW5jIGZ1bmN0aW9uIHkoZSxuKXtjb25zdCB0PWF3YWl0IGUucG9zdCgiUnVudGltZS5nZXRQcm9wZXJ0aWVzIix7b2JqZWN0SWQ6bixvd25Qcm9wZXJ0aWVzOiEwfSksbz17fTtmb3IoY29uc3QgbiBvZiB0LnJlc3VsdClpZihuPy52YWx1ZT8ub2JqZWN0SWQmJiJBcnJheSI9PT1uPy52YWx1ZS5jbGFzc05hbWUpe2NvbnN0IHQ9bi52YWx1ZS5vYmplY3RJZDthd2FpdCB2KGUsdCxuLm5hbWUsbyl9ZWxzZSBpZihuPy52YWx1ZT8ub2JqZWN0SWQmJiJPYmplY3QiPT09bj8udmFsdWU/LmNsYXNzTmFtZSl7Y29uc3QgdD1uLnZhbHVlLm9iamVjdElkO2F3YWl0ICQoZSx0LG4ubmFtZSxvKX1lbHNlIG4/LnZhbHVlJiZ3KG4sbyk7cmV0dXJuIG99bGV0IGg7KGFzeW5jIGZ1bmN0aW9uKCl7Y29uc3Qgbj1uZXcgZTtuLmNvbm5lY3RUb01haW5UaHJlYWQoKSxiKCJDb25uZWN0ZWQgdG8gbWFpbiB0aHJlYWQiKTtsZXQgbz0hMTtuLm9uKCJEZWJ1Z2dlci5yZXN1bWVkIiwoKCk9PntvPSExfSkpLG4ub24oIkRlYnVnZ2VyLnBhdXNlZCIsKGU9PntvPSEwLGFzeW5jIGZ1bmN0aW9uKGUsbix7cmVhc29uOm8sZGF0YTpyLGNhbGxGcmFtZXM6aX0pe2lmKCJleGNlcHRpb24iIT09byYmInByb21pc2VSZWplY3Rpb24iIT09bylyZXR1cm47aD8uKCk7Y29uc3Qgcz1mdW5jdGlvbihlLG4pe2lmKHZvaWQgMCE9PW4pcmV0dXJuIGZ1bmN0aW9uKGUpe2lmKHZvaWQgMCE9PWUpcmV0dXJuIGUuc2xpY2UoLTEwKS5yZWR1Y2UoKChlLG4pPT5gJHtlfSwke24uZnVuY3Rpb259LCR7bi5saW5lbm99LCR7bi5jb2xub31gKSwiIil9KGUobiwxKSl9KG4scj8uZGVzY3JpcHRpb24pO2lmKG51bGw9PXMpcmV0dXJuO2NvbnN0IGM9W107Zm9yKGxldCBuPTA7bjxpLmxlbmd0aDtuKyspe2NvbnN0e3Njb3BlQ2hhaW46dCxmdW5jdGlvbk5hbWU6byx0aGlzOnJ9PWlbbl0scz10LmZpbmQoKGU9PiJsb2NhbCI9PT1lLnR5cGUpKSxhPSJnbG9iYWwiIT09ci5jbGFzc05hbWUmJnIuY2xhc3NOYW1lP2Ake3IuY2xhc3NOYW1lfS4ke299YDpvO2lmKHZvaWQgMD09PXM/Lm9iamVjdC5vYmplY3RJZCljW25dPXtmdW5jdGlvbjphfTtlbHNle2NvbnN0IHQ9YXdhaXQgeShlLHMub2JqZWN0Lm9iamVjdElkKTtjW25dPXtmdW5jdGlvbjphLHZhcnM6dH19fXQ/LnBvc3RNZXNzYWdlKHtleGNlcHRpb25IYXNoOnMsZnJhbWVzOmN9KX0obixtLGUucGFyYW1zKS50aGVuKCgoKT0+bz9uLnBvc3QoIkRlYnVnZ2VyLnJlc3VtZSIpOlByb21pc2UucmVzb2x2ZSgpKSwoZT0+e30pKX0pKSxhd2FpdCBuLnBvc3QoIkRlYnVnZ2VyLmVuYWJsZSIpO2NvbnN0IHI9ITEhPT1nLmNhcHR1cmVBbGxFeGNlcHRpb25zO2lmKGF3YWl0IG4ucG9zdCgiRGVidWdnZXIuc2V0UGF1c2VPbkV4Y2VwdGlvbnMiLHtzdGF0ZTpyPyJhbGwiOiJ1bmNhdWdodCJ9KSxyKXtjb25zdCBlPWcubWF4RXhjZXB0aW9uc1BlclNlY29uZHx8NTA7aD1mdW5jdGlvbihlLG4sdCl7bGV0IG89MCxyPTUsaT0wO3JldHVybiBzZXRJbnRlcnZhbCgoKCk9PnswPT09aT9vPmUmJihyKj0yLHQocikscj44NjQwMCYmKHI9ODY0MDApLGk9cik6KGktPTEsMD09PWkmJm4oKSksbz0wfSksMWUzKS51bnJlZigpLCgpPT57bys9MX19KGUsKGFzeW5jKCk9PntiKCJSYXRlLWxpbWl0IGxpZnRlZC4iKSxhd2FpdCBuLnBvc3QoIkRlYnVnZ2VyLnNldFBhdXNlT25FeGNlcHRpb25zIix7c3RhdGU6ImFsbCJ9KX0pLChhc3luYyBlPT57YihgUmF0ZS1saW1pdCBleGNlZWRlZC4gRGlzYWJsaW5nIGNhcHR1cmluZyBvZiBjYXVnaHQgZXhjZXB0aW9ucyBmb3IgJHtlfSBzZWNvbmRzLmApLGF3YWl0IG4ucG9zdCgiRGVidWdnZXIuc2V0UGF1c2VPbkV4Y2VwdGlvbnMiLHtzdGF0ZToidW5jYXVnaHQifSl9KSl9fSkoKS5jYXRjaCgoZT0+e2IoIkZhaWxlZCB0byBzdGFydCBkZWJ1Z2dlciIsZSl9KSksc2V0SW50ZXJ2YWwoKCgpPT57fSksMWU0KTs=';
963
+
964
+ function log$1(...args) {
965
+ logger.log('[LocalVariables]', ...args);
966
+ }
967
+
968
+ /**
969
+ * Adds local variables to exception frames
970
+ */
971
+ const localVariablesAsyncIntegration = defineIntegration(((
972
+ integrationOptions = {},
973
+ ) => {
974
+ const cachedFrames = new LRUMap(20);
975
+
976
+ function addLocalVariablesToException(exception) {
977
+ const hash = hashFrames(_optionalChain$9([exception, 'optionalAccess', _ => _.stacktrace, 'optionalAccess', _2 => _2.frames]));
978
+
979
+ if (hash === undefined) {
980
+ return;
981
+ }
982
+
983
+ // Check if we have local variables for an exception that matches the hash
984
+ // remove is identical to get but also removes the entry from the cache
985
+ const cachedFrame = cachedFrames.remove(hash);
986
+
987
+ if (cachedFrame === undefined) {
988
+ return;
989
+ }
990
+
991
+ // Filter out frames where the function name is `new Promise` since these are in the error.stack frames
992
+ // but do not appear in the debugger call frames
993
+ const frames = (_optionalChain$9([exception, 'access', _3 => _3.stacktrace, 'optionalAccess', _4 => _4.frames]) || []).filter(frame => frame.function !== 'new Promise');
994
+
995
+ for (let i = 0; i < frames.length; i++) {
996
+ // Sentry frames are in reverse order
997
+ const frameIndex = frames.length - i - 1;
998
+
999
+ // Drop out if we run out of frames to match up
1000
+ if (!frames[frameIndex] || !cachedFrame[i]) {
1001
+ break;
1002
+ }
1003
+
1004
+ if (
1005
+ // We need to have vars to add
1006
+ cachedFrame[i].vars === undefined ||
1007
+ // We're not interested in frames that are not in_app because the vars are not relevant
1008
+ frames[frameIndex].in_app === false ||
1009
+ // The function names need to match
1010
+ !functionNamesMatch(frames[frameIndex].function, cachedFrame[i].function)
1011
+ ) {
1012
+ continue;
1013
+ }
1014
+
1015
+ frames[frameIndex].vars = cachedFrame[i].vars;
1016
+ }
1017
+ }
1018
+
1019
+ function addLocalVariablesToEvent(event) {
1020
+ for (const exception of _optionalChain$9([event, 'access', _5 => _5.exception, 'optionalAccess', _6 => _6.values]) || []) {
1021
+ addLocalVariablesToException(exception);
1022
+ }
1023
+
1024
+ return event;
1025
+ }
1026
+
1027
+ async function startInspector() {
1028
+ // We load inspector dynamically because on some platforms Node is built without inspector support
1029
+ const inspector = await import('inspector');
1030
+ if (!inspector.url()) {
1031
+ inspector.open(0);
1032
+ }
1033
+ }
1034
+
1035
+ function startWorker(options) {
1036
+ const worker = new Worker(new URL(`data:application/javascript;base64,${base64WorkerScript$1}`), {
1037
+ workerData: options,
1038
+ });
1039
+
1040
+ process.on('exit', () => {
1041
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
1042
+ worker.terminate();
1043
+ });
1044
+
1045
+ worker.on('message', ({ exceptionHash, frames }) => {
1046
+ cachedFrames.set(exceptionHash, frames);
1047
+ });
1048
+
1049
+ worker.once('error', (err) => {
1050
+ log$1('Worker error', err);
1051
+ });
1052
+
1053
+ worker.once('exit', (code) => {
1054
+ log$1('Worker exit', code);
1055
+ });
1056
+
1057
+ // Ensure this thread can't block app exit
1058
+ worker.unref();
1059
+ }
1060
+
1061
+ return {
1062
+ name: 'LocalVariablesAsync',
1063
+ setup(client) {
1064
+ const clientOptions = client.getOptions();
1065
+
1066
+ if (!clientOptions.includeLocalVariables) {
1067
+ return;
1068
+ }
1069
+
1070
+ const options = {
1071
+ ...integrationOptions,
1072
+ debug: logger.isEnabled(),
1073
+ };
1074
+
1075
+ startInspector().then(
1076
+ () => {
1077
+ try {
1078
+ startWorker(options);
1079
+ } catch (e) {
1080
+ logger.error('Failed to start worker', e);
1081
+ }
1082
+ },
1083
+ e => {
1084
+ logger.error('Failed to start inspector', e);
1085
+ },
1086
+ );
1087
+ },
1088
+ processEvent(event) {
1089
+ return addLocalVariablesToEvent(event);
1090
+ },
1091
+ };
1092
+ }) );
1093
+
960
1094
  function _optionalChain$8(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
961
1095
  /** Creates a container for callbacks to be called sequentially */
962
1096
  function createCallbackList(complete) {
@@ -1319,7 +1453,9 @@ const _localVariablesSyncIntegration = ((
1319
1453
  */
1320
1454
  const localVariablesSyncIntegration = defineIntegration(_localVariablesSyncIntegration);
1321
1455
 
1322
- const localVariablesIntegration = localVariablesSyncIntegration;
1456
+ const localVariablesIntegration = (options = {}) => {
1457
+ return NODE_VERSION.major < 19 ? localVariablesSyncIntegration(options) : localVariablesAsyncIntegration(options);
1458
+ };
1323
1459
 
1324
1460
  let moduleCache;
1325
1461
 
@@ -1654,10 +1790,10 @@ function handleRejection(
1654
1790
  /* eslint-enable no-console */
1655
1791
  }
1656
1792
 
1793
+ function _optionalChain$7(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
1657
1794
  // This string is a placeholder that gets overwritten with the worker code.
1658
- const base64WorkerScript = 'aW1wb3J0IHsgU2Vzc2lvbiB9IGZyb20gJ2luc3BlY3Rvcic7CmltcG9ydCB7IHdvcmtlckRhdGEsIHBhcmVudFBvcnQgfSBmcm9tICd3b3JrZXJfdGhyZWFkcyc7CmltcG9ydCB7IHBvc2l4LCBzZXAgfSBmcm9tICdwYXRoJzsKaW1wb3J0ICogYXMgaHR0cCQxIGZyb20gJ25vZGU6aHR0cCc7CmltcG9ydCAqIGFzIGh0dHBzIGZyb20gJ25vZGU6aHR0cHMnOwppbXBvcnQgeyBSZWFkYWJsZSB9IGZyb20gJ3N0cmVhbSc7CmltcG9ydCB7IGNyZWF0ZUd6aXAgfSBmcm9tICd6bGliJzsKaW1wb3J0ICogYXMgbmV0IGZyb20gJ25ldCc7CmltcG9ydCAqIGFzIHRscyBmcm9tICd0bHMnOwppbXBvcnQgKiBhcyBodHRwIGZyb20gJ2h0dHAnOwoKLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC91bmJvdW5kLW1ldGhvZApjb25zdCBvYmplY3RUb1N0cmluZyA9IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmc7CgovKioKICogQ2hlY2tzIHdoZXRoZXIgZ2l2ZW4gdmFsdWUncyB0eXBlIGlzIG9uZSBvZiBhIGZldyBFcnJvciBvciBFcnJvci1saWtlCiAqIHtAbGluayBpc0Vycm9yfS4KICoKICogQHBhcmFtIHdhdCBBIHZhbHVlIHRvIGJlIGNoZWNrZWQuCiAqIEByZXR1cm5zIEEgYm9vbGVhbiByZXByZXNlbnRpbmcgdGhlIHJlc3VsdC4KICovCmZ1bmN0aW9uIGlzRXJyb3Iod2F0KSB7CiAgc3dpdGNoIChvYmplY3RUb1N0cmluZy5jYWxsKHdhdCkpIHsKICAgIGNhc2UgJ1tvYmplY3QgRXJyb3JdJzoKICAgIGNhc2UgJ1tvYmplY3QgRXhjZXB0aW9uXSc6CiAgICBjYXNlICdbb2JqZWN0IERPTUV4Y2VwdGlvbl0nOgogICAgICByZXR1cm4gdHJ1ZTsKICAgIGRlZmF1bHQ6CiAgICAgIHJldHVybiBpc0luc3RhbmNlT2Yod2F0LCBFcnJvcik7CiAgfQp9Ci8qKgogKiBDaGVja3Mgd2hldGhlciBnaXZlbiB2YWx1ZSBpcyBhbiBpbnN0YW5jZSBvZiB0aGUgZ2l2ZW4gYnVpbHQtaW4gY2xhc3MuCiAqCiAqIEBwYXJhbSB3YXQgVGhlIHZhbHVlIHRvIGJlIGNoZWNrZWQKICogQHBhcmFtIGNsYXNzTmFtZQogKiBAcmV0dXJucyBBIGJvb2xlYW4gcmVwcmVzZW50aW5nIHRoZSByZXN1bHQuCiAqLwpmdW5jdGlvbiBpc0J1aWx0aW4od2F0LCBjbGFzc05hbWUpIHsKICByZXR1cm4gb2JqZWN0VG9TdHJpbmcuY2FsbCh3YXQpID09PSBgW29iamVjdCAke2NsYXNzTmFtZX1dYDsKfQoKLyoqCiAqIENoZWNrcyB3aGV0aGVyIGdpdmVuIHZhbHVlJ3MgdHlwZSBpcyBhIHN0cmluZwogKiB7QGxpbmsgaXNTdHJpbmd9LgogKgogKiBAcGFyYW0gd2F0IEEgdmFsdWUgdG8gYmUgY2hlY2tlZC4KICogQHJldHVybnMgQSBib29sZWFuIHJlcHJlc2VudGluZyB0aGUgcmVzdWx0LgogKi8KZnVuY3Rpb24gaXNTdHJpbmcod2F0KSB7CiAgcmV0dXJuIGlzQnVpbHRpbih3YXQsICdTdHJpbmcnKTsKfQoKLyoqCiAqIENoZWNrcyB3aGV0aGVyIGdpdmVuIHZhbHVlJ3MgdHlwZSBpcyBhbiBvYmplY3QgbGl0ZXJhbCwgb3IgYSBjbGFzcyBpbnN0YW5jZS4KICoge0BsaW5rIGlzUGxhaW5PYmplY3R9LgogKgogKiBAcGFyYW0gd2F0IEEgdmFsdWUgdG8gYmUgY2hlY2tlZC4KICogQHJldHVybnMgQSBib29sZWFuIHJlcHJlc2VudGluZyB0aGUgcmVzdWx0LgogKi8KZnVuY3Rpb24gaXNQbGFpbk9iamVjdCh3YXQpIHsKICByZXR1cm4gaXNCdWlsdGluKHdhdCwgJ09iamVjdCcpOwp9CgovKioKICogQ2hlY2tzIHdoZXRoZXIgZ2l2ZW4gdmFsdWUncyB0eXBlIGlzIGFuIEV2ZW50IGluc3RhbmNlCiAqIHtAbGluayBpc0V2ZW50fS4KICoKICogQHBhcmFtIHdhdCBBIHZhbHVlIHRvIGJlIGNoZWNrZWQuCiAqIEByZXR1cm5zIEEgYm9vbGVhbiByZXByZXNlbnRpbmcgdGhlIHJlc3VsdC4KICovCmZ1bmN0aW9uIGlzRXZlbnQod2F0KSB7CiAgcmV0dXJuIHR5cGVvZiBFdmVudCAhPT0gJ3VuZGVmaW5lZCcgJiYgaXNJbnN0YW5jZU9mKHdhdCwgRXZlbnQpOwp9CgovKioKICogQ2hlY2tzIHdoZXRoZXIgZ2l2ZW4gdmFsdWUncyB0eXBlIGlzIGFuIEVsZW1lbnQgaW5zdGFuY2UKICoge0BsaW5rIGlzRWxlbWVudH0uCiAqCiAqIEBwYXJhbSB3YXQgQSB2YWx1ZSB0byBiZSBjaGVja2VkLgogKiBAcmV0dXJucyBBIGJvb2xlYW4gcmVwcmVzZW50aW5nIHRoZSByZXN1bHQuCiAqLwpmdW5jdGlvbiBpc0VsZW1lbnQod2F0KSB7CiAgcmV0dXJuIHR5cGVvZiBFbGVtZW50ICE9PSAndW5kZWZpbmVkJyAmJiBpc0luc3RhbmNlT2Yod2F0LCBFbGVtZW50KTsKfQoKLyoqCiAqIENoZWNrcyB3aGV0aGVyIGdpdmVuIHZhbHVlIGhhcyBhIHRoZW4gZnVuY3Rpb24uCiAqIEBwYXJhbSB3YXQgQSB2YWx1ZSB0byBiZSBjaGVja2VkLgogKi8KZnVuY3Rpb24gaXNUaGVuYWJsZSh3YXQpIHsKICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVuc2FmZS1tZW1iZXItYWNjZXNzCiAgcmV0dXJuIEJvb2xlYW4od2F0ICYmIHdhdC50aGVuICYmIHR5cGVvZiB3YXQudGhlbiA9PT0gJ2Z1bmN0aW9uJyk7Cn0KCi8qKgogKiBDaGVja3Mgd2hldGhlciBnaXZlbiB2YWx1ZSdzIHR5cGUgaXMgYSBTeW50aGV0aWNFdmVudAogKiB7QGxpbmsgaXNTeW50aGV0aWNFdmVudH0uCiAqCiAqIEBwYXJhbSB3YXQgQSB2YWx1ZSB0byBiZSBjaGVja2VkLgogKiBAcmV0dXJucyBBIGJvb2xlYW4gcmVwcmVzZW50aW5nIHRoZSByZXN1bHQuCiAqLwpmdW5jdGlvbiBpc1N5bnRoZXRpY0V2ZW50KHdhdCkgewogIHJldHVybiBpc1BsYWluT2JqZWN0KHdhdCkgJiYgJ25hdGl2ZUV2ZW50JyBpbiB3YXQgJiYgJ3ByZXZlbnREZWZhdWx0JyBpbiB3YXQgJiYgJ3N0b3BQcm9wYWdhdGlvbicgaW4gd2F0Owp9CgovKioKICogQ2hlY2tzIHdoZXRoZXIgZ2l2ZW4gdmFsdWUncyB0eXBlIGlzIGFuIGluc3RhbmNlIG9mIHByb3ZpZGVkIGNvbnN0cnVjdG9yLgogKiB7QGxpbmsgaXNJbnN0YW5jZU9mfS4KICoKICogQHBhcmFtIHdhdCBBIHZhbHVlIHRvIGJlIGNoZWNrZWQuCiAqIEBwYXJhbSBiYXNlIEEgY29uc3RydWN0b3IgdG8gYmUgdXNlZCBpbiBhIGNoZWNrLgogKiBAcmV0dXJucyBBIGJvb2xlYW4gcmVwcmVzZW50aW5nIHRoZSByZXN1bHQuCiAqLwpmdW5jdGlvbiBpc0luc3RhbmNlT2Yod2F0LCBiYXNlKSB7CiAgdHJ5IHsKICAgIHJldHVybiB3YXQgaW5zdGFuY2VvZiBiYXNlOwogIH0gY2F0Y2ggKF9lKSB7CiAgICByZXR1cm4gZmFsc2U7CiAgfQp9CgovKioKICogQ2hlY2tzIHdoZXRoZXIgZ2l2ZW4gdmFsdWUncyB0eXBlIGlzIGEgVnVlIFZpZXdNb2RlbC4KICoKICogQHBhcmFtIHdhdCBBIHZhbHVlIHRvIGJlIGNoZWNrZWQuCiAqIEByZXR1cm5zIEEgYm9vbGVhbiByZXByZXNlbnRpbmcgdGhlIHJlc3VsdC4KICovCmZ1bmN0aW9uIGlzVnVlVmlld01vZGVsKHdhdCkgewogIC8vIE5vdCB1c2luZyBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nIGJlY2F1c2UgaW4gVnVlIDMgaXQgd291bGQgcmVhZCB0aGUgaW5zdGFuY2UncyBTeW1ib2woU3ltYm9sLnRvU3RyaW5nVGFnKSBwcm9wZXJ0eS4KICByZXR1cm4gISEodHlwZW9mIHdhdCA9PT0gJ29iamVjdCcgJiYgd2F0ICE9PSBudWxsICYmICgod2F0ICkuX19pc1Z1ZSB8fCAod2F0ICkuX2lzVnVlKSk7Cn0KCi8qKiBJbnRlcm5hbCBnbG9iYWwgd2l0aCBjb21tb24gcHJvcGVydGllcyBhbmQgU2VudHJ5IGV4dGVuc2lvbnMgICovCgovKiogR2V0J3MgdGhlIGdsb2JhbCBvYmplY3QgZm9yIHRoZSBjdXJyZW50IEphdmFTY3JpcHQgcnVudGltZSAqLwpjb25zdCBHTE9CQUxfT0JKID0gZ2xvYmFsVGhpcyA7CgovKioKICogUmV0dXJucyBhIGdsb2JhbCBzaW5nbGV0b24gY29udGFpbmVkIGluIHRoZSBnbG9iYWwgYF9fU0VOVFJZX19gIG9iamVjdC4KICoKICogSWYgdGhlIHNpbmdsZXRvbiBkb2Vzbid0IGFscmVhZHkgZXhpc3QgaW4gYF9fU0VOVFJZX19gLCBpdCB3aWxsIGJlIGNyZWF0ZWQgdXNpbmcgdGhlIGdpdmVuIGZhY3RvcnkKICogZnVuY3Rpb24gYW5kIGFkZGVkIHRvIHRoZSBgX19TRU5UUllfX2Agb2JqZWN0LgogKgogKiBAcGFyYW0gbmFtZSBuYW1lIG9mIHRoZSBnbG9iYWwgc2luZ2xldG9uIG9uIF9fU0VOVFJZX18KICogQHBhcmFtIGNyZWF0b3IgY3JlYXRvciBGYWN0b3J5IGZ1bmN0aW9uIHRvIGNyZWF0ZSB0aGUgc2luZ2xldG9uIGlmIGl0IGRvZXNuJ3QgYWxyZWFkeSBleGlzdCBvbiBgX19TRU5UUllfX2AKICogQHBhcmFtIG9iaiAoT3B0aW9uYWwpIFRoZSBnbG9iYWwgb2JqZWN0IG9uIHdoaWNoIHRvIGxvb2sgZm9yIGBfX1NFTlRSWV9fYCwgaWYgbm90IGBHTE9CQUxfT0JKYCdzIHJldHVybiB2YWx1ZQogKiBAcmV0dXJucyB0aGUgc2luZ2xldG9uCiAqLwpmdW5jdGlvbiBnZXRHbG9iYWxTaW5nbGV0b24obmFtZSwgY3JlYXRvciwgb2JqKSB7CiAgY29uc3QgZ2JsID0gKG9iaiB8fCBHTE9CQUxfT0JKKSA7CiAgY29uc3QgX19TRU5UUllfXyA9IChnYmwuX19TRU5UUllfXyA9IGdibC5fX1NFTlRSWV9fIHx8IHt9KTsKICBjb25zdCBzaW5nbGV0b24gPSBfX1NFTlRSWV9fW25hbWVdIHx8IChfX1NFTlRSWV9fW25hbWVdID0gY3JlYXRvcigpKTsKICByZXR1cm4gc2luZ2xldG9uOwp9Cgpjb25zdCBXSU5ET1cgPSBHTE9CQUxfT0JKIDsKCmNvbnN0IERFRkFVTFRfTUFYX1NUUklOR19MRU5HVEggPSA4MDsKCi8qKgogKiBHaXZlbiBhIGNoaWxkIERPTSBlbGVtZW50LCByZXR1cm5zIGEgcXVlcnktc2VsZWN0b3Igc3RhdGVtZW50IGRlc2NyaWJpbmcgdGhhdAogKiBhbmQgaXRzIGFuY2VzdG9ycwogKiBlLmcuIFtIVE1MRWxlbWVudF0gPT4gYm9keSA+IGRpdiA+IGlucHV0I2Zvby5idG5bbmFtZT1iYXpdCiAqIEByZXR1cm5zIGdlbmVyYXRlZCBET00gcGF0aAogKi8KZnVuY3Rpb24gaHRtbFRyZWVBc1N0cmluZygKICBlbGVtLAogIG9wdGlvbnMgPSB7fSwKKSB7CiAgaWYgKCFlbGVtKSB7CiAgICByZXR1cm4gJzx1bmtub3duPic7CiAgfQoKICAvLyB0cnkvY2F0Y2ggYm90aDoKICAvLyAtIGFjY2Vzc2luZyBldmVudC50YXJnZXQgKHNlZSBnZXRzZW50cnkvcmF2ZW4tanMjODM4LCAjNzY4KQogIC8vIC0gYGh0bWxUcmVlQXNTdHJpbmdgIGJlY2F1c2UgaXQncyBjb21wbGV4LCBhbmQganVzdCBhY2Nlc3NpbmcgdGhlIERPTSBpbmNvcnJlY3RseQogIC8vIC0gY2FuIHRocm93IGFuIGV4Y2VwdGlvbiBpbiBzb21lIGNpcmN1bXN0YW5jZXMuCiAgdHJ5IHsKICAgIGxldCBjdXJyZW50RWxlbSA9IGVsZW0gOwogICAgY29uc3QgTUFYX1RSQVZFUlNFX0hFSUdIVCA9IDU7CiAgICBjb25zdCBvdXQgPSBbXTsKICAgIGxldCBoZWlnaHQgPSAwOwogICAgbGV0IGxlbiA9IDA7CiAgICBjb25zdCBzZXBhcmF0b3IgPSAnID4gJzsKICAgIGNvbnN0IHNlcExlbmd0aCA9IHNlcGFyYXRvci5sZW5ndGg7CiAgICBsZXQgbmV4dFN0cjsKICAgIGNvbnN0IGtleUF0dHJzID0gQXJyYXkuaXNBcnJheShvcHRpb25zKSA/IG9wdGlvbnMgOiBvcHRpb25zLmtleUF0dHJzOwogICAgY29uc3QgbWF4U3RyaW5nTGVuZ3RoID0gKCFBcnJheS5pc0FycmF5KG9wdGlvbnMpICYmIG9wdGlvbnMubWF4U3RyaW5nTGVuZ3RoKSB8fCBERUZBVUxUX01BWF9TVFJJTkdfTEVOR1RIOwoKICAgIHdoaWxlIChjdXJyZW50RWxlbSAmJiBoZWlnaHQrKyA8IE1BWF9UUkFWRVJTRV9IRUlHSFQpIHsKICAgICAgbmV4dFN0ciA9IF9odG1sRWxlbWVudEFzU3RyaW5nKGN1cnJlbnRFbGVtLCBrZXlBdHRycyk7CiAgICAgIC8vIGJhaWwgb3V0IGlmCiAgICAgIC8vIC0gbmV4dFN0ciBpcyB0aGUgJ2h0bWwnIGVsZW1lbnQKICAgICAgLy8gLSB0aGUgbGVuZ3RoIG9mIHRoZSBzdHJpbmcgdGhhdCB3b3VsZCBiZSBjcmVhdGVkIGV4Y2VlZHMgbWF4U3RyaW5nTGVuZ3RoCiAgICAgIC8vICAgKGlnbm9yZSB0aGlzIGxpbWl0IGlmIHdlIGFyZSBvbiB0aGUgZmlyc3QgaXRlcmF0aW9uKQogICAgICBpZiAobmV4dFN0ciA9PT0gJ2h0bWwnIHx8IChoZWlnaHQgPiAxICYmIGxlbiArIG91dC5sZW5ndGggKiBzZXBMZW5ndGggKyBuZXh0U3RyLmxlbmd0aCA+PSBtYXhTdHJpbmdMZW5ndGgpKSB7CiAgICAgICAgYnJlYWs7CiAgICAgIH0KCiAgICAgIG91dC5wdXNoKG5leHRTdHIpOwoKICAgICAgbGVuICs9IG5leHRTdHIubGVuZ3RoOwogICAgICBjdXJyZW50RWxlbSA9IGN1cnJlbnRFbGVtLnBhcmVudE5vZGU7CiAgICB9CgogICAgcmV0dXJuIG91dC5yZXZlcnNlKCkuam9pbihzZXBhcmF0b3IpOwogIH0gY2F0Y2ggKF9vTykgewogICAgcmV0dXJuICc8dW5rbm93bj4nOwogIH0KfQoKLyoqCiAqIFJldHVybnMgYSBzaW1wbGUsIHF1ZXJ5LXNlbGVjdG9yIHJlcHJlc2VudGF0aW9uIG9mIGEgRE9NIGVsZW1lbnQKICogZS5nLiBbSFRNTEVsZW1lbnRdID0+IGlucHV0I2Zvby5idG5bbmFtZT1iYXpdCiAqIEByZXR1cm5zIGdlbmVyYXRlZCBET00gcGF0aAogKi8KZnVuY3Rpb24gX2h0bWxFbGVtZW50QXNTdHJpbmcoZWwsIGtleUF0dHJzKSB7CiAgY29uc3QgZWxlbSA9IGVsCgo7CgogIGNvbnN0IG91dCA9IFtdOwogIGxldCBjbGFzc05hbWU7CiAgbGV0IGNsYXNzZXM7CiAgbGV0IGtleTsKICBsZXQgYXR0cjsKICBsZXQgaTsKCiAgaWYgKCFlbGVtIHx8ICFlbGVtLnRhZ05hbWUpIHsKICAgIHJldHVybiAnJzsKICB9CgogIC8vIEB0cy1leHBlY3QtZXJyb3IgV0lORE9XIGhhcyBIVE1MRWxlbWVudAogIGlmIChXSU5ET1cuSFRNTEVsZW1lbnQpIHsKICAgIC8vIElmIHVzaW5nIHRoZSBjb21wb25lbnQgbmFtZSBhbm5vdGF0aW9uIHBsdWdpbiwgdGhpcyB2YWx1ZSBtYXkgYmUgYXZhaWxhYmxlIG9uIHRoZSBET00gbm9kZQogICAgaWYgKGVsZW0gaW5zdGFuY2VvZiBIVE1MRWxlbWVudCAmJiBlbGVtLmRhdGFzZXQpIHsKICAgICAgaWYgKGVsZW0uZGF0YXNldFsnc2VudHJ5Q29tcG9uZW50J10pIHsKICAgICAgICByZXR1cm4gZWxlbS5kYXRhc2V0WydzZW50cnlDb21wb25lbnQnXTsKICAgICAgfQogICAgICBpZiAoZWxlbS5kYXRhc2V0WydzZW50cnlFbGVtZW50J10pIHsKICAgICAgICByZXR1cm4gZWxlbS5kYXRhc2V0WydzZW50cnlFbGVtZW50J107CiAgICAgIH0KICAgIH0KICB9CgogIG91dC5wdXNoKGVsZW0udGFnTmFtZS50b0xvd2VyQ2FzZSgpKTsKCiAgLy8gUGFpcnMgb2YgYXR0cmlidXRlIGtleXMgZGVmaW5lZCBpbiBgc2VyaWFsaXplQXR0cmlidXRlYCBhbmQgdGhlaXIgdmFsdWVzIG9uIGVsZW1lbnQuCiAgY29uc3Qga2V5QXR0clBhaXJzID0KICAgIGtleUF0dHJzICYmIGtleUF0dHJzLmxlbmd0aAogICAgICA/IGtleUF0dHJzLmZpbHRlcihrZXlBdHRyID0+IGVsZW0uZ2V0QXR0cmlidXRlKGtleUF0dHIpKS5tYXAoa2V5QXR0ciA9PiBba2V5QXR0ciwgZWxlbS5nZXRBdHRyaWJ1dGUoa2V5QXR0cildKQogICAgICA6IG51bGw7CgogIGlmIChrZXlBdHRyUGFpcnMgJiYga2V5QXR0clBhaXJzLmxlbmd0aCkgewogICAga2V5QXR0clBhaXJzLmZvckVhY2goa2V5QXR0clBhaXIgPT4gewogICAgICBvdXQucHVzaChgWyR7a2V5QXR0clBhaXJbMF19PSIke2tleUF0dHJQYWlyWzFdfSJdYCk7CiAgICB9KTsKICB9IGVsc2UgewogICAgaWYgKGVsZW0uaWQpIHsKICAgICAgb3V0LnB1c2goYCMke2VsZW0uaWR9YCk7CiAgICB9CgogICAgY2xhc3NOYW1lID0gZWxlbS5jbGFzc05hbWU7CiAgICBpZiAoY2xhc3NOYW1lICYmIGlzU3RyaW5nKGNsYXNzTmFtZSkpIHsKICAgICAgY2xhc3NlcyA9IGNsYXNzTmFtZS5zcGxpdCgvXHMrLyk7CiAgICAgIGZvciAoaSA9IDA7IGkgPCBjbGFzc2VzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgb3V0LnB1c2goYC4ke2NsYXNzZXNbaV19YCk7CiAgICAgIH0KICAgIH0KICB9CiAgY29uc3QgYWxsb3dlZEF0dHJzID0gWydhcmlhLWxhYmVsJywgJ3R5cGUnLCAnbmFtZScsICd0aXRsZScsICdhbHQnXTsKICBmb3IgKGkgPSAwOyBpIDwgYWxsb3dlZEF0dHJzLmxlbmd0aDsgaSsrKSB7CiAgICBrZXkgPSBhbGxvd2VkQXR0cnNbaV07CiAgICBhdHRyID0gZWxlbS5nZXRBdHRyaWJ1dGUoa2V5KTsKICAgIGlmIChhdHRyKSB7CiAgICAgIG91dC5wdXNoKGBbJHtrZXl9PSIke2F0dHJ9Il1gKTsKICAgIH0KICB9CiAgcmV0dXJuIG91dC5qb2luKCcnKTsKfQoKLyoqCiAqIFRoaXMgc2VydmVzIGFzIGEgYnVpbGQgdGltZSBmbGFnIHRoYXQgd2lsbCBiZSB0cnVlIGJ5IGRlZmF1bHQsIGJ1dCBmYWxzZSBpbiBub24tZGVidWcgYnVpbGRzIG9yIGlmIHVzZXJzIHJlcGxhY2UgYF9fU0VOVFJZX0RFQlVHX19gIGluIHRoZWlyIGdlbmVyYXRlZCBjb2RlLgogKgogKiBBVFRFTlRJT046IFRoaXMgY29uc3RhbnQgbXVzdCBuZXZlciBjcm9zcyBwYWNrYWdlIGJvdW5kYXJpZXMgKGkuZS4gYmUgZXhwb3J0ZWQpIHRvIGd1YXJhbnRlZSB0aGF0IGl0IGNhbiBiZSB1c2VkIGZvciB0cmVlIHNoYWtpbmcuCiAqLwpjb25zdCBERUJVR19CVUlMRCQxID0gKHR5cGVvZiBfX1NFTlRSWV9ERUJVR19fID09PSAndW5kZWZpbmVkJyB8fCBfX1NFTlRSWV9ERUJVR19fKTsKCi8qKiBQcmVmaXggZm9yIGxvZ2dpbmcgc3RyaW5ncyAqLwpjb25zdCBQUkVGSVggPSAnU2VudHJ5IExvZ2dlciAnOwoKY29uc3QgQ09OU09MRV9MRVZFTFMgPSBbCiAgJ2RlYnVnJywKICAnaW5mbycsCiAgJ3dhcm4nLAogICdlcnJvcicsCiAgJ2xvZycsCiAgJ2Fzc2VydCcsCiAgJ3RyYWNlJywKXSA7CgovKiogVGhpcyBtYXkgYmUgbXV0YXRlZCBieSB0aGUgY29uc29sZSBpbnN0cnVtZW50YXRpb24uICovCmNvbnN0IG9yaWdpbmFsQ29uc29sZU1ldGhvZHMKCiA9IHt9OwoKLyoqIEpTRG9jICovCgovKioKICogVGVtcG9yYXJpbHkgZGlzYWJsZSBzZW50cnkgY29uc29sZSBpbnN0cnVtZW50YXRpb25zLgogKgogKiBAcGFyYW0gY2FsbGJhY2sgVGhlIGZ1bmN0aW9uIHRvIHJ1biBhZ2FpbnN0IHRoZSBvcmlnaW5hbCBgY29uc29sZWAgbWVzc2FnZXMKICogQHJldHVybnMgVGhlIHJlc3VsdHMgb2YgdGhlIGNhbGxiYWNrCiAqLwpmdW5jdGlvbiBjb25zb2xlU2FuZGJveChjYWxsYmFjaykgewogIGlmICghKCdjb25zb2xlJyBpbiBHTE9CQUxfT0JKKSkgewogICAgcmV0dXJuIGNhbGxiYWNrKCk7CiAgfQoKICBjb25zdCBjb25zb2xlID0gR0xPQkFMX09CSi5jb25zb2xlIDsKICBjb25zdCB3cmFwcGVkRnVuY3MgPSB7fTsKCiAgY29uc3Qgd3JhcHBlZExldmVscyA9IE9iamVjdC5rZXlzKG9yaWdpbmFsQ29uc29sZU1ldGhvZHMpIDsKCiAgLy8gUmVzdG9yZSBhbGwgd3JhcHBlZCBjb25zb2xlIG1ldGhvZHMKICB3cmFwcGVkTGV2ZWxzLmZvckVhY2gobGV2ZWwgPT4gewogICAgY29uc3Qgb3JpZ2luYWxDb25zb2xlTWV0aG9kID0gb3JpZ2luYWxDb25zb2xlTWV0aG9kc1tsZXZlbF0gOwogICAgd3JhcHBlZEZ1bmNzW2xldmVsXSA9IGNvbnNvbGVbbGV2ZWxdIDsKICAgIGNvbnNvbGVbbGV2ZWxdID0gb3JpZ2luYWxDb25zb2xlTWV0aG9kOwogIH0pOwoKICB0cnkgewogICAgcmV0dXJuIGNhbGxiYWNrKCk7CiAgfSBmaW5hbGx5IHsKICAgIC8vIFJldmVydCByZXN0b3JhdGlvbiB0byB3cmFwcGVkIHN0YXRlCiAgICB3cmFwcGVkTGV2ZWxzLmZvckVhY2gobGV2ZWwgPT4gewogICAgICBjb25zb2xlW2xldmVsXSA9IHdyYXBwZWRGdW5jc1tsZXZlbF0gOwogICAgfSk7CiAgfQp9CgpmdW5jdGlvbiBtYWtlTG9nZ2VyKCkgewogIGxldCBlbmFibGVkID0gZmFsc2U7CiAgY29uc3QgbG9nZ2VyID0gewogICAgZW5hYmxlOiAoKSA9PiB7CiAgICAgIGVuYWJsZWQgPSB0cnVlOwogICAgfSwKICAgIGRpc2FibGU6ICgpID0+IHsKICAgICAgZW5hYmxlZCA9IGZhbHNlOwogICAgfSwKICAgIGlzRW5hYmxlZDogKCkgPT4gZW5hYmxlZCwKICB9OwoKICBpZiAoREVCVUdfQlVJTEQkMSkgewogICAgQ09OU09MRV9MRVZFTFMuZm9yRWFjaChuYW1lID0+IHsKICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnkKICAgICAgbG9nZ2VyW25hbWVdID0gKC4uLmFyZ3MpID0+IHsKICAgICAgICBpZiAoZW5hYmxlZCkgewogICAgICAgICAgY29uc29sZVNhbmRib3goKCkgPT4gewogICAgICAgICAgICBHTE9CQUxfT0JKLmNvbnNvbGVbbmFtZV0oYCR7UFJFRklYfVske25hbWV9XTpgLCAuLi5hcmdzKTsKICAgICAgICAgIH0pOwogICAgICAgIH0KICAgICAgfTsKICAgIH0pOwogIH0gZWxzZSB7CiAgICBDT05TT0xFX0xFVkVMUy5mb3JFYWNoKG5hbWUgPT4gewogICAgICBsb2dnZXJbbmFtZV0gPSAoKSA9PiB1bmRlZmluZWQ7CiAgICB9KTsKICB9CgogIHJldHVybiBsb2dnZXIgOwp9Cgpjb25zdCBsb2dnZXIgPSBtYWtlTG9nZ2VyKCk7CgovKioKICogUmVuZGVycyB0aGUgc3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIHRoaXMgRHNuLgogKgogKiBCeSBkZWZhdWx0LCB0aGlzIHdpbGwgcmVuZGVyIHRoZSBwdWJsaWMgcmVwcmVzZW50YXRpb24gd2l0aG91dCB0aGUgcGFzc3dvcmQKICogY29tcG9uZW50LiBUbyBnZXQgdGhlIGRlcHJlY2F0ZWQgcHJpdmF0ZSByZXByZXNlbnRhdGlvbiwgc2V0IGB3aXRoUGFzc3dvcmRgCiAqIHRvIHRydWUuCiAqCiAqIEBwYXJhbSB3aXRoUGFzc3dvcmQgV2hlbiBzZXQgdG8gdHJ1ZSwgdGhlIHBhc3N3b3JkIHdpbGwgYmUgaW5jbHVkZWQuCiAqLwpmdW5jdGlvbiBkc25Ub1N0cmluZyhkc24sIHdpdGhQYXNzd29yZCA9IGZhbHNlKSB7CiAgY29uc3QgeyBob3N0LCBwYXRoLCBwYXNzLCBwb3J0LCBwcm9qZWN0SWQsIHByb3RvY29sLCBwdWJsaWNLZXkgfSA9IGRzbjsKICByZXR1cm4gKAogICAgYCR7cHJvdG9jb2x9Oi8vJHtwdWJsaWNLZXl9JHt3aXRoUGFzc3dvcmQgJiYgcGFzcyA/IGA6JHtwYXNzfWAgOiAnJ31gICsKICAgIGBAJHtob3N0fSR7cG9ydCA/IGA6JHtwb3J0fWAgOiAnJ30vJHtwYXRoID8gYCR7cGF0aH0vYCA6IHBhdGh9JHtwcm9qZWN0SWR9YAogICk7Cn0KCi8qKiBBbiBlcnJvciBlbWl0dGVkIGJ5IFNlbnRyeSBTREtzIGFuZCByZWxhdGVkIHV0aWxpdGllcy4gKi8KY2xhc3MgU2VudHJ5RXJyb3IgZXh0ZW5kcyBFcnJvciB7CiAgLyoqIERpc3BsYXkgbmFtZSBvZiB0aGlzIGVycm9yIGluc3RhbmNlLiAqLwoKICAgY29uc3RydWN0b3IoIG1lc3NhZ2UsIGxvZ0xldmVsID0gJ3dhcm4nKSB7CiAgICBzdXBlcihtZXNzYWdlKTt0aGlzLm1lc3NhZ2UgPSBtZXNzYWdlOwogICAgdGhpcy5uYW1lID0gbmV3LnRhcmdldC5wcm90b3R5cGUuY29uc3RydWN0b3IubmFtZTsKICAgIC8vIFRoaXMgc2V0cyB0aGUgcHJvdG90eXBlIHRvIGJlIGBFcnJvcmAsIG5vdCBgU2VudHJ5RXJyb3JgLiBJdCdzIHVuY2xlYXIgd2h5IHdlIGRvIHRoaXMsIGJ1dCBjb21tZW50aW5nIHRoaXMgbGluZQogICAgLy8gb3V0IGNhdXNlcyB2YXJpb3VzIChzZWVtaW5nbHkgdG90YWxseSB1bnJlbGF0ZWQpIHBsYXl3cmlnaHQgdGVzdHMgY29uc2lzdGVudGx5IHRpbWUgb3V0LiBGWUksIHRoaXMgbWFrZXMKICAgIC8vIGluc3RhbmNlcyBvZiBgU2VudHJ5RXJyb3JgIGZhaWwgYG9iaiBpbnN0YW5jZW9mIFNlbnRyeUVycm9yYCBjaGVja3MuCiAgICBPYmplY3Quc2V0UHJvdG90eXBlT2YodGhpcywgbmV3LnRhcmdldC5wcm90b3R5cGUpOwogICAgdGhpcy5sb2dMZXZlbCA9IGxvZ0xldmVsOwogIH0KfQoKLyoqCiAqIERlZmluZXMgYSBub24tZW51bWVyYWJsZSBwcm9wZXJ0eSBvbiB0aGUgZ2l2ZW4gb2JqZWN0LgogKgogKiBAcGFyYW0gb2JqIFRoZSBvYmplY3Qgb24gd2hpY2ggdG8gc2V0IHRoZSBwcm9wZXJ0eQogKiBAcGFyYW0gbmFtZSBUaGUgbmFtZSBvZiB0aGUgcHJvcGVydHkgdG8gYmUgc2V0CiAqIEBwYXJhbSB2YWx1ZSBUaGUgdmFsdWUgdG8gd2hpY2ggdG8gc2V0IHRoZSBwcm9wZXJ0eQogKi8KZnVuY3Rpb24gYWRkTm9uRW51bWVyYWJsZVByb3BlcnR5KG9iaiwgbmFtZSwgdmFsdWUpIHsKICB0cnkgewogICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KG9iaiwgbmFtZSwgewogICAgICAvLyBlbnVtZXJhYmxlOiBmYWxzZSwgLy8gdGhlIGRlZmF1bHQsIHNvIHdlIGNhbiBzYXZlIG9uIGJ1bmRsZSBzaXplIGJ5IG5vdCBleHBsaWNpdGx5IHNldHRpbmcgaXQKICAgICAgdmFsdWU6IHZhbHVlLAogICAgICB3cml0YWJsZTogdHJ1ZSwKICAgICAgY29uZmlndXJhYmxlOiB0cnVlLAogICAgfSk7CiAgfSBjYXRjaCAob19PKSB7CiAgICBERUJVR19CVUlMRCQxICYmIGxvZ2dlci5sb2coYEZhaWxlZCB0byBhZGQgbm9uLWVudW1lcmFibGUgcHJvcGVydHkgIiR7bmFtZX0iIHRvIG9iamVjdGAsIG9iaik7CiAgfQp9CgovKioKICogRW5jb2RlcyBnaXZlbiBvYmplY3QgaW50byB1cmwtZnJpZW5kbHkgZm9ybWF0CiAqCiAqIEBwYXJhbSBvYmplY3QgQW4gb2JqZWN0IHRoYXQgY29udGFpbnMgc2VyaWFsaXphYmxlIHZhbHVlcwogKiBAcmV0dXJucyBzdHJpbmcgRW5jb2RlZAogKi8KZnVuY3Rpb24gdXJsRW5jb2RlKG9iamVjdCkgewogIHJldHVybiBPYmplY3Qua2V5cyhvYmplY3QpCiAgICAubWFwKGtleSA9PiBgJHtlbmNvZGVVUklDb21wb25lbnQoa2V5KX09JHtlbmNvZGVVUklDb21wb25lbnQob2JqZWN0W2tleV0pfWApCiAgICAuam9pbignJicpOwp9CgovKioKICogVHJhbnNmb3JtcyBhbnkgYEVycm9yYCBvciBgRXZlbnRgIGludG8gYSBwbGFpbiBvYmplY3Qgd2l0aCBhbGwgb2YgdGhlaXIgZW51bWVyYWJsZSBwcm9wZXJ0aWVzLCBhbmQgc29tZSBvZiB0aGVpcgogKiBub24tZW51bWVyYWJsZSBwcm9wZXJ0aWVzIGF0dGFjaGVkLgogKgogKiBAcGFyYW0gdmFsdWUgSW5pdGlhbCBzb3VyY2UgdGhhdCB3ZSBoYXZlIHRvIHRyYW5zZm9ybSBpbiBvcmRlciBmb3IgaXQgdG8gYmUgdXNhYmxlIGJ5IHRoZSBzZXJpYWxpemVyCiAqIEByZXR1cm5zIEFuIEV2ZW50IG9yIEVycm9yIHR1cm5lZCBpbnRvIGFuIG9iamVjdCAtIG9yIHRoZSB2YWx1ZSBhcmd1cm1lbnQgaXRzZWxmLCB3aGVuIHZhbHVlIGlzIG5laXRoZXIgYW4gRXZlbnQgbm9yCiAqICBhbiBFcnJvci4KICovCmZ1bmN0aW9uIGNvbnZlcnRUb1BsYWluT2JqZWN0KAogIHZhbHVlLAopCgogewogIGlmIChpc0Vycm9yKHZhbHVlKSkgewogICAgcmV0dXJuIHsKICAgICAgbWVzc2FnZTogdmFsdWUubWVzc2FnZSwKICAgICAgbmFtZTogdmFsdWUubmFtZSwKICAgICAgc3RhY2s6IHZhbHVlLnN0YWNrLAogICAgICAuLi5nZXRPd25Qcm9wZXJ0aWVzKHZhbHVlKSwKICAgIH07CiAgfSBlbHNlIGlmIChpc0V2ZW50KHZhbHVlKSkgewogICAgY29uc3QgbmV3T2JqCgogPSB7CiAgICAgIHR5cGU6IHZhbHVlLnR5cGUsCiAgICAgIHRhcmdldDogc2VyaWFsaXplRXZlbnRUYXJnZXQodmFsdWUudGFyZ2V0KSwKICAgICAgY3VycmVudFRhcmdldDogc2VyaWFsaXplRXZlbnRUYXJnZXQodmFsdWUuY3VycmVudFRhcmdldCksCiAgICAgIC4uLmdldE93blByb3BlcnRpZXModmFsdWUpLAogICAgfTsKCiAgICBpZiAodHlwZW9mIEN1c3RvbUV2ZW50ICE9PSAndW5kZWZpbmVkJyAmJiBpc0luc3RhbmNlT2YodmFsdWUsIEN1c3RvbUV2ZW50KSkgewogICAgICBuZXdPYmouZGV0YWlsID0gdmFsdWUuZGV0YWlsOwogICAgfQoKICAgIHJldHVybiBuZXdPYmo7CiAgfSBlbHNlIHsKICAgIHJldHVybiB2YWx1ZTsKICB9Cn0KCi8qKiBDcmVhdGVzIGEgc3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIHRoZSB0YXJnZXQgb2YgYW4gYEV2ZW50YCBvYmplY3QgKi8KZnVuY3Rpb24gc2VyaWFsaXplRXZlbnRUYXJnZXQodGFyZ2V0KSB7CiAgdHJ5IHsKICAgIHJldHVybiBpc0VsZW1lbnQodGFyZ2V0KSA/IGh0bWxUcmVlQXNTdHJpbmcodGFyZ2V0KSA6IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbCh0YXJnZXQpOwogIH0gY2F0Y2ggKF9vTykgewogICAgcmV0dXJuICc8dW5rbm93bj4nOwogIH0KfQoKLyoqIEZpbHRlcnMgb3V0IGFsbCBidXQgYW4gb2JqZWN0J3Mgb3duIHByb3BlcnRpZXMgKi8KZnVuY3Rpb24gZ2V0T3duUHJvcGVydGllcyhvYmopIHsKICBpZiAodHlwZW9mIG9iaiA9PT0gJ29iamVjdCcgJiYgb2JqICE9PSBudWxsKSB7CiAgICBjb25zdCBleHRyYWN0ZWRQcm9wcyA9IHt9OwogICAgZm9yIChjb25zdCBwcm9wZXJ0eSBpbiBvYmopIHsKICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChvYmosIHByb3BlcnR5KSkgewogICAgICAgIGV4dHJhY3RlZFByb3BzW3Byb3BlcnR5XSA9IChvYmogKVtwcm9wZXJ0eV07CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBleHRyYWN0ZWRQcm9wczsKICB9IGVsc2UgewogICAgcmV0dXJuIHt9OwogIH0KfQoKLyoqCiAqIEdpdmVuIGFueSBvYmplY3QsIHJldHVybiBhIG5ldyBvYmplY3QgaGF2aW5nIHJlbW92ZWQgYWxsIGZpZWxkcyB3aG9zZSB2YWx1ZSB3YXMgYHVuZGVmaW5lZGAuCiAqIFdvcmtzIHJlY3Vyc2l2ZWx5IG9uIG9iamVjdHMgYW5kIGFycmF5cy4KICoKICogQXR0ZW50aW9uOiBUaGlzIGZ1bmN0aW9uIGtlZXBzIGNpcmN1bGFyIHJlZmVyZW5jZXMgaW4gdGhlIHJldHVybmVkIG9iamVjdC4KICovCmZ1bmN0aW9uIGRyb3BVbmRlZmluZWRLZXlzKGlucHV0VmFsdWUpIHsKICAvLyBUaGlzIG1hcCBrZWVwcyB0cmFjayBvZiB3aGF0IGFscmVhZHkgdmlzaXRlZCBub2RlcyBtYXAgdG8uCiAgLy8gT3VyIFNldCAtIGJhc2VkIG1lbW9CdWlsZGVyIGRvZXNuJ3Qgd29yayBoZXJlIGJlY2F1c2Ugd2Ugd2FudCB0byB0aGUgb3V0cHV0IG9iamVjdCB0byBoYXZlIHRoZSBzYW1lIGNpcmN1bGFyCiAgLy8gcmVmZXJlbmNlcyBhcyB0aGUgaW5wdXQgb2JqZWN0LgogIGNvbnN0IG1lbW9pemF0aW9uTWFwID0gbmV3IE1hcCgpOwoKICAvLyBUaGlzIGZ1bmN0aW9uIGp1c3QgcHJveGllcyBgX2Ryb3BVbmRlZmluZWRLZXlzYCB0byBrZWVwIHRoZSBgbWVtb0J1aWxkZXJgIG91dCBvZiB0aGlzIGZ1bmN0aW9uJ3MgQVBJCiAgcmV0dXJuIF9kcm9wVW5kZWZpbmVkS2V5cyhpbnB1dFZhbHVlLCBtZW1vaXphdGlvbk1hcCk7Cn0KCmZ1bmN0aW9uIF9kcm9wVW5kZWZpbmVkS2V5cyhpbnB1dFZhbHVlLCBtZW1vaXphdGlvbk1hcCkgewogIGlmIChpc1Bvam8oaW5wdXRWYWx1ZSkpIHsKICAgIC8vIElmIHRoaXMgbm9kZSBoYXMgYWxyZWFkeSBiZWVuIHZpc2l0ZWQgZHVlIHRvIGEgY2lyY3VsYXIgcmVmZXJlbmNlLCByZXR1cm4gdGhlIG9iamVjdCBpdCB3YXMgbWFwcGVkIHRvIGluIHRoZSBuZXcgb2JqZWN0CiAgICBjb25zdCBtZW1vVmFsID0gbWVtb2l6YXRpb25NYXAuZ2V0KGlucHV0VmFsdWUpOwogICAgaWYgKG1lbW9WYWwgIT09IHVuZGVmaW5lZCkgewogICAgICByZXR1cm4gbWVtb1ZhbCA7CiAgICB9CgogICAgY29uc3QgcmV0dXJuVmFsdWUgPSB7fTsKICAgIC8vIFN0b3JlIHRoZSBtYXBwaW5nIG9mIHRoaXMgdmFsdWUgaW4gY2FzZSB3ZSB2aXNpdCBpdCBhZ2FpbiwgaW4gY2FzZSBvZiBjaXJjdWxhciBkYXRhCiAgICBtZW1vaXphdGlvbk1hcC5zZXQoaW5wdXRWYWx1ZSwgcmV0dXJuVmFsdWUpOwoKICAgIGZvciAoY29uc3Qga2V5IG9mIE9iamVjdC5rZXlzKGlucHV0VmFsdWUpKSB7CiAgICAgIGlmICh0eXBlb2YgaW5wdXRWYWx1ZVtrZXldICE9PSAndW5kZWZpbmVkJykgewogICAgICAgIHJldHVyblZhbHVlW2tleV0gPSBfZHJvcFVuZGVmaW5lZEtleXMoaW5wdXRWYWx1ZVtrZXldLCBtZW1vaXphdGlvbk1hcCk7CiAgICAgIH0KICAgIH0KCiAgICByZXR1cm4gcmV0dXJuVmFsdWUgOwogIH0KCiAgaWYgKEFycmF5LmlzQXJyYXkoaW5wdXRWYWx1ZSkpIHsKICAgIC8vIElmIHRoaXMgbm9kZSBoYXMgYWxyZWFkeSBiZWVuIHZpc2l0ZWQgZHVlIHRvIGEgY2lyY3VsYXIgcmVmZXJlbmNlLCByZXR1cm4gdGhlIGFycmF5IGl0IHdhcyBtYXBwZWQgdG8gaW4gdGhlIG5ldyBvYmplY3QKICAgIGNvbnN0IG1lbW9WYWwgPSBtZW1vaXphdGlvbk1hcC5nZXQoaW5wdXRWYWx1ZSk7CiAgICBpZiAobWVtb1ZhbCAhPT0gdW5kZWZpbmVkKSB7CiAgICAgIHJldHVybiBtZW1vVmFsIDsKICAgIH0KCiAgICBjb25zdCByZXR1cm5WYWx1ZSA9IFtdOwogICAgLy8gU3RvcmUgdGhlIG1hcHBpbmcgb2YgdGhpcyB2YWx1ZSBpbiBjYXNlIHdlIHZpc2l0IGl0IGFnYWluLCBpbiBjYXNlIG9mIGNpcmN1bGFyIGRhdGEKICAgIG1lbW9pemF0aW9uTWFwLnNldChpbnB1dFZhbHVlLCByZXR1cm5WYWx1ZSk7CgogICAgaW5wdXRWYWx1ZS5mb3JFYWNoKChpdGVtKSA9PiB7CiAgICAgIHJldHVyblZhbHVlLnB1c2goX2Ryb3BVbmRlZmluZWRLZXlzKGl0ZW0sIG1lbW9pemF0aW9uTWFwKSk7CiAgICB9KTsKCiAgICByZXR1cm4gcmV0dXJuVmFsdWUgOwogIH0KCiAgcmV0dXJuIGlucHV0VmFsdWU7Cn0KCmZ1bmN0aW9uIGlzUG9qbyhpbnB1dCkgewogIGlmICghaXNQbGFpbk9iamVjdChpbnB1dCkpIHsKICAgIHJldHVybiBmYWxzZTsKICB9CgogIHRyeSB7CiAgICBjb25zdCBuYW1lID0gKE9iamVjdC5nZXRQcm90b3R5cGVPZihpbnB1dCkgKS5jb25zdHJ1Y3Rvci5uYW1lOwogICAgcmV0dXJuICFuYW1lIHx8IG5hbWUgPT09ICdPYmplY3QnOwogIH0gY2F0Y2ggKGUpIHsKICAgIHJldHVybiB0cnVlOwogIH0KfQoKY29uc3QgU1RBQ0tUUkFDRV9GUkFNRV9MSU1JVCA9IDUwOwpjb25zdCBVTktOT1dOX0ZVTkNUSU9OID0gJz8nOwpjb25zdCBTVFJJUF9GUkFNRV9SRUdFWFAgPSAvY2FwdHVyZU1lc3NhZ2V8Y2FwdHVyZUV4Y2VwdGlvbi87CgovKioKICogUmVtb3ZlcyBTZW50cnkgZnJhbWVzIGZyb20gdGhlIHRvcCBhbmQgYm90dG9tIG9mIHRoZSBzdGFjayBpZiBwcmVzZW50IGFuZCBlbmZvcmNlcyBhIGxpbWl0IG9mIG1heCBudW1iZXIgb2YgZnJhbWVzLgogKiBBc3N1bWVzIHN0YWNrIGlucHV0IGlzIG9yZGVyZWQgZnJvbSB0b3AgdG8gYm90dG9tIGFuZCByZXR1cm5zIHRoZSByZXZlcnNlIHJlcHJlc2VudGF0aW9uIHNvIGNhbGwgc2l0ZSBvZiB0aGUKICogZnVuY3Rpb24gdGhhdCBjYXVzZWQgdGhlIGNyYXNoIGlzIHRoZSBsYXN0IGZyYW1lIGluIHRoZSBhcnJheS4KICogQGhpZGRlbgogKi8KZnVuY3Rpb24gc3RyaXBTZW50cnlGcmFtZXNBbmRSZXZlcnNlKHN0YWNrKSB7CiAgaWYgKCFzdGFjay5sZW5ndGgpIHsKICAgIHJldHVybiBbXTsKICB9CgogIGNvbnN0IGxvY2FsU3RhY2sgPSBBcnJheS5mcm9tKHN0YWNrKTsKCiAgLy8gSWYgc3RhY2sgc3RhcnRzIHdpdGggb25lIG9mIG91ciBBUEkgY2FsbHMsIHJlbW92ZSBpdCAoc3RhcnRzLCBtZWFuaW5nIGl0J3MgdGhlIHRvcCBvZiB0aGUgc3RhY2sgLSBha2EgbGFzdCBjYWxsKQogIGlmICgvc2VudHJ5V3JhcHBlZC8udGVzdChsb2NhbFN0YWNrW2xvY2FsU3RhY2subGVuZ3RoIC0gMV0uZnVuY3Rpb24gfHwgJycpKSB7CiAgICBsb2NhbFN0YWNrLnBvcCgpOwogIH0KCiAgLy8gUmV2ZXJzaW5nIGluIHRoZSBtaWRkbGUgb2YgdGhlIHByb2NlZHVyZSBhbGxvd3MgdXMgdG8ganVzdCBwb3AgdGhlIHZhbHVlcyBvZmYgdGhlIHN0YWNrCiAgbG9jYWxTdGFjay5yZXZlcnNlKCk7CgogIC8vIElmIHN0YWNrIGVuZHMgd2l0aCBvbmUgb2Ygb3VyIGludGVybmFsIEFQSSBjYWxscywgcmVtb3ZlIGl0IChlbmRzLCBtZWFuaW5nIGl0J3MgdGhlIGJvdHRvbSBvZiB0aGUgc3RhY2sgLSBha2EgdG9wLW1vc3QgY2FsbCkKICBpZiAoU1RSSVBfRlJBTUVfUkVHRVhQLnRlc3QobG9jYWxTdGFja1tsb2NhbFN0YWNrLmxlbmd0aCAtIDFdLmZ1bmN0aW9uIHx8ICcnKSkgewogICAgbG9jYWxTdGFjay5wb3AoKTsKCiAgICAvLyBXaGVuIHVzaW5nIHN5bnRoZXRpYyBldmVudHMsIHdlIHdpbGwgaGF2ZSBhIDIgbGV2ZWxzIGRlZXAgc3RhY2ssIGFzIGBuZXcgRXJyb3IoJ1NlbnRyeSBzeW50aGV0aWNFeGNlcHRpb24nKWAKICAgIC8vIGlzIHByb2R1Y2VkIHdpdGhpbiB0aGUgaHViIGl0c2VsZiwgbWFraW5nIGl0OgogICAgLy8KICAgIC8vICAgU2VudHJ5LmNhcHR1cmVFeGNlcHRpb24oKQogICAgLy8gICBnZXRDdXJyZW50SHViKCkuY2FwdHVyZUV4Y2VwdGlvbigpCiAgICAvLwogICAgLy8gaW5zdGVhZCBvZiBqdXN0IHRoZSB0b3AgYFNlbnRyeWAgY2FsbCBpdHNlbGYuCiAgICAvLyBUaGlzIGZvcmNlcyB1cyB0byBwb3NzaWJseSBzdHJpcCBhbiBhZGRpdGlvbmFsIGZyYW1lIGluIHRoZSBleGFjdCBzYW1lIHdhcyBhcyBhYm92ZS4KICAgIGlmIChTVFJJUF9GUkFNRV9SRUdFWFAudGVzdChsb2NhbFN0YWNrW2xvY2FsU3RhY2subGVuZ3RoIC0gMV0uZnVuY3Rpb24gfHwgJycpKSB7CiAgICAgIGxvY2FsU3RhY2sucG9wKCk7CiAgICB9CiAgfQoKICByZXR1cm4gbG9jYWxTdGFjay5zbGljZSgwLCBTVEFDS1RSQUNFX0ZSQU1FX0xJTUlUKS5tYXAoZnJhbWUgPT4gKHsKICAgIC4uLmZyYW1lLAogICAgZmlsZW5hbWU6IGZyYW1lLmZpbGVuYW1lIHx8IGxvY2FsU3RhY2tbbG9jYWxTdGFjay5sZW5ndGggLSAxXS5maWxlbmFtZSwKICAgIGZ1bmN0aW9uOiBmcmFtZS5mdW5jdGlvbiB8fCBVTktOT1dOX0ZVTkNUSU9OLAogIH0pKTsKfQoKY29uc3QgZGVmYXVsdEZ1bmN0aW9uTmFtZSA9ICc8YW5vbnltb3VzPic7CgovKioKICogU2FmZWx5IGV4dHJhY3QgZnVuY3Rpb24gbmFtZSBmcm9tIGl0c2VsZgogKi8KZnVuY3Rpb24gZ2V0RnVuY3Rpb25OYW1lKGZuKSB7CiAgdHJ5IHsKICAgIGlmICghZm4gfHwgdHlwZW9mIGZuICE9PSAnZnVuY3Rpb24nKSB7CiAgICAgIHJldHVybiBkZWZhdWx0RnVuY3Rpb25OYW1lOwogICAgfQogICAgcmV0dXJuIGZuLm5hbWUgfHwgZGVmYXVsdEZ1bmN0aW9uTmFtZTsKICB9IGNhdGNoIChlKSB7CiAgICAvLyBKdXN0IGFjY2Vzc2luZyBjdXN0b20gcHJvcHMgaW4gc29tZSBTZWxlbml1bSBlbnZpcm9ubWVudHMKICAgIC8vIGNhbiBjYXVzZSBhICJQZXJtaXNzaW9uIGRlbmllZCIgZXhjZXB0aW9uIChzZWUgcmF2ZW4tanMjNDk1KS4KICAgIHJldHVybiBkZWZhdWx0RnVuY3Rpb25OYW1lOwogIH0KfQoKLyogZXNsaW50LWRpc2FibGUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVuc2FmZS1tZW1iZXItYWNjZXNzICovCi8qIGVzbGludC1kaXNhYmxlIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnkgKi8KCi8qKgogKiBIZWxwZXIgdG8gZGVjeWNsZSBqc29uIG9iamVjdHMKICovCmZ1bmN0aW9uIG1lbW9CdWlsZGVyKCkgewogIGNvbnN0IGhhc1dlYWtTZXQgPSB0eXBlb2YgV2Vha1NldCA9PT0gJ2Z1bmN0aW9uJzsKICBjb25zdCBpbm5lciA9IGhhc1dlYWtTZXQgPyBuZXcgV2Vha1NldCgpIDogW107CiAgZnVuY3Rpb24gbWVtb2l6ZShvYmopIHsKICAgIGlmIChoYXNXZWFrU2V0KSB7CiAgICAgIGlmIChpbm5lci5oYXMob2JqKSkgewogICAgICAgIHJldHVybiB0cnVlOwogICAgICB9CiAgICAgIGlubmVyLmFkZChvYmopOwogICAgICByZXR1cm4gZmFsc2U7CiAgICB9CiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L3ByZWZlci1mb3Itb2YKICAgIGZvciAobGV0IGkgPSAwOyBpIDwgaW5uZXIubGVuZ3RoOyBpKyspIHsKICAgICAgY29uc3QgdmFsdWUgPSBpbm5lcltpXTsKICAgICAgaWYgKHZhbHVlID09PSBvYmopIHsKICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgfQogICAgfQogICAgaW5uZXIucHVzaChvYmopOwogICAgcmV0dXJuIGZhbHNlOwogIH0KCiAgZnVuY3Rpb24gdW5tZW1vaXplKG9iaikgewogICAgaWYgKGhhc1dlYWtTZXQpIHsKICAgICAgaW5uZXIuZGVsZXRlKG9iaik7CiAgICB9IGVsc2UgewogICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGlubmVyLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgaWYgKGlubmVyW2ldID09PSBvYmopIHsKICAgICAgICAgIGlubmVyLnNwbGljZShpLCAxKTsKICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgICAgfQogICAgfQogIH0KICByZXR1cm4gW21lbW9pemUsIHVubWVtb2l6ZV07Cn0KCi8qKgogKiBVVUlENCBnZW5lcmF0b3IKICoKICogQHJldHVybnMgc3RyaW5nIEdlbmVyYXRlZCBVVUlENC4KICovCmZ1bmN0aW9uIHV1aWQ0KCkgewogIGNvbnN0IGdibCA9IEdMT0JBTF9PQkogOwogIGNvbnN0IGNyeXB0byA9IGdibC5jcnlwdG8gfHwgZ2JsLm1zQ3J5cHRvOwoKICBsZXQgZ2V0UmFuZG9tQnl0ZSA9ICgpID0+IE1hdGgucmFuZG9tKCkgKiAxNjsKICB0cnkgewogICAgaWYgKGNyeXB0byAmJiBjcnlwdG8ucmFuZG9tVVVJRCkgewogICAgICByZXR1cm4gY3J5cHRvLnJhbmRvbVVVSUQoKS5yZXBsYWNlKC8tL2csICcnKTsKICAgIH0KICAgIGlmIChjcnlwdG8gJiYgY3J5cHRvLmdldFJhbmRvbVZhbHVlcykgewogICAgICBnZXRSYW5kb21CeXRlID0gKCkgPT4gewogICAgICAgIC8vIGNyeXB0by5nZXRSYW5kb21WYWx1ZXMgbWlnaHQgcmV0dXJuIHVuZGVmaW5lZCBpbnN0ZWFkIG9mIHRoZSB0eXBlZCBhcnJheQogICAgICAgIC8vIGluIG9sZCBDaHJvbWl1bSB2ZXJzaW9ucyAoZS5nLiAyMy4wLjEyMzUuMCAoMTUxNDIyKSkKICAgICAgICAvLyBIb3dldmVyLCBgdHlwZWRBcnJheWAgaXMgc3RpbGwgZmlsbGVkIGluLXBsYWNlLgogICAgICAgIC8vIEBzZWUgaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQVBJL0NyeXB0by9nZXRSYW5kb21WYWx1ZXMjdHlwZWRhcnJheQogICAgICAgIGNvbnN0IHR5cGVkQXJyYXkgPSBuZXcgVWludDhBcnJheSgxKTsKICAgICAgICBjcnlwdG8uZ2V0UmFuZG9tVmFsdWVzKHR5cGVkQXJyYXkpOwogICAgICAgIHJldHVybiB0eXBlZEFycmF5WzBdOwogICAgICB9OwogICAgfQogIH0gY2F0Y2ggKF8pIHsKICAgIC8vIHNvbWUgcnVudGltZXMgY2FuIGNyYXNoIGludm9raW5nIGNyeXB0bwogICAgLy8gaHR0cHM6Ly9naXRodWIuY29tL2dldHNlbnRyeS9zZW50cnktamF2YXNjcmlwdC9pc3N1ZXMvODkzNQogIH0KCiAgLy8gaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy8xMDUwMzQvaG93LXRvLWNyZWF0ZS1hLWd1aWQtdXVpZC1pbi1qYXZhc2NyaXB0LzIxMTc1MjMjMjExNzUyMwogIC8vIENvbmNhdGVuYXRpbmcgdGhlIGZvbGxvd2luZyBudW1iZXJzIGFzIHN0cmluZ3MgcmVzdWx0cyBpbiAnMTAwMDAwMDAxMDAwNDAwMDgwMDAxMDAwMDAwMDAwMDAnCiAgcmV0dXJuICgoWzFlN10gKSArIDFlMyArIDRlMyArIDhlMyArIDFlMTEpLnJlcGxhY2UoL1swMThdL2csIGMgPT4KICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1iaXR3aXNlCiAgICAoKGMgKSBeICgoZ2V0UmFuZG9tQnl0ZSgpICYgMTUpID4+ICgoYyApIC8gNCkpKS50b1N0cmluZygxNiksCiAgKTsKfQoKLyoqCiAqIENoZWNrcyB3aGV0aGVyIHRoZSBnaXZlbiBpbnB1dCBpcyBhbHJlYWR5IGFuIGFycmF5LCBhbmQgaWYgaXQgaXNuJ3QsIHdyYXBzIGl0IGluIG9uZS4KICoKICogQHBhcmFtIG1heWJlQXJyYXkgSW5wdXQgdG8gdHVybiBpbnRvIGFuIGFycmF5LCBpZiBuZWNlc3NhcnkKICogQHJldHVybnMgVGhlIGlucHV0LCBpZiBhbHJlYWR5IGFuIGFycmF5LCBvciBhbiBhcnJheSB3aXRoIHRoZSBpbnB1dCBhcyB0aGUgb25seSBlbGVtZW50LCBpZiBub3QKICovCmZ1bmN0aW9uIGFycmF5aWZ5KG1heWJlQXJyYXkpIHsKICByZXR1cm4gQXJyYXkuaXNBcnJheShtYXliZUFycmF5KSA/IG1heWJlQXJyYXkgOiBbbWF5YmVBcnJheV07Cn0KCi8qKgogKiBSZWN1cnNpdmVseSBub3JtYWxpemVzIHRoZSBnaXZlbiBvYmplY3QuCiAqCiAqIC0gQ3JlYXRlcyBhIGNvcHkgdG8gcHJldmVudCBvcmlnaW5hbCBpbnB1dCBtdXRhdGlvbgogKiAtIFNraXBzIG5vbi1lbnVtZXJhYmxlIHByb3BlcnRpZXMKICogLSBXaGVuIHN0cmluZ2lmeWluZywgY2FsbHMgYHRvSlNPTmAgaWYgaW1wbGVtZW50ZWQKICogLSBSZW1vdmVzIGNpcmN1bGFyIHJlZmVyZW5jZXMKICogLSBUcmFuc2xhdGVzIG5vbi1zZXJpYWxpemFibGUgdmFsdWVzIChgdW5kZWZpbmVkYC9gTmFOYC9mdW5jdGlvbnMpIHRvIHNlcmlhbGl6YWJsZSBmb3JtYXQKICogLSBUcmFuc2xhdGVzIGtub3duIGdsb2JhbCBvYmplY3RzL2NsYXNzZXMgdG8gYSBzdHJpbmcgcmVwcmVzZW50YXRpb25zCiAqIC0gVGFrZXMgY2FyZSBvZiBgRXJyb3JgIG9iamVjdCBzZXJpYWxpemF0aW9uCiAqIC0gT3B0aW9uYWxseSBsaW1pdHMgZGVwdGggb2YgZmluYWwgb3V0cHV0CiAqIC0gT3B0aW9uYWxseSBsaW1pdHMgbnVtYmVyIG9mIHByb3BlcnRpZXMvZWxlbWVudHMgaW5jbHVkZWQgaW4gYW55IHNpbmdsZSBvYmplY3QvYXJyYXkKICoKICogQHBhcmFtIGlucHV0IFRoZSBvYmplY3QgdG8gYmUgbm9ybWFsaXplZC4KICogQHBhcmFtIGRlcHRoIFRoZSBtYXggZGVwdGggdG8gd2hpY2ggdG8gbm9ybWFsaXplIHRoZSBvYmplY3QuIChBbnl0aGluZyBkZWVwZXIgc3RyaW5naWZpZWQgd2hvbGUuKQogKiBAcGFyYW0gbWF4UHJvcGVydGllcyBUaGUgbWF4IG51bWJlciBvZiBlbGVtZW50cyBvciBwcm9wZXJ0aWVzIHRvIGJlIGluY2x1ZGVkIGluIGFueSBzaW5nbGUgYXJyYXkgb3IKICogb2JqZWN0IGluIHRoZSBub3JtYWxsaXplZCBvdXRwdXQuCiAqIEByZXR1cm5zIEEgbm9ybWFsaXplZCB2ZXJzaW9uIG9mIHRoZSBvYmplY3QsIG9yIGAiKipub24tc2VyaWFsaXphYmxlKioiYCBpZiBhbnkgZXJyb3JzIGFyZSB0aHJvd24gZHVyaW5nIG5vcm1hbGl6YXRpb24uCiAqLwovLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueQpmdW5jdGlvbiBub3JtYWxpemUoaW5wdXQsIGRlcHRoID0gMTAwLCBtYXhQcm9wZXJ0aWVzID0gK0luZmluaXR5KSB7CiAgdHJ5IHsKICAgIC8vIHNpbmNlIHdlJ3JlIGF0IHRoZSBvdXRlcm1vc3QgbGV2ZWwsIHdlIGRvbid0IHByb3ZpZGUgYSBrZXkKICAgIHJldHVybiB2aXNpdCgnJywgaW5wdXQsIGRlcHRoLCBtYXhQcm9wZXJ0aWVzKTsKICB9IGNhdGNoIChlcnIpIHsKICAgIHJldHVybiB7IEVSUk9SOiBgKipub24tc2VyaWFsaXphYmxlKiogKCR7ZXJyfSlgIH07CiAgfQp9CgovKioKICogVmlzaXRzIGEgbm9kZSB0byBwZXJmb3JtIG5vcm1hbGl6YXRpb24gb24gaXQKICoKICogQHBhcmFtIGtleSBUaGUga2V5IGNvcnJlc3BvbmRpbmcgdG8gdGhlIGdpdmVuIG5vZGUKICogQHBhcmFtIHZhbHVlIFRoZSBub2RlIHRvIGJlIHZpc2l0ZWQKICogQHBhcmFtIGRlcHRoIE9wdGlvbmFsIG51bWJlciBpbmRpY2F0aW5nIHRoZSBtYXhpbXVtIHJlY3Vyc2lvbiBkZXB0aAogKiBAcGFyYW0gbWF4UHJvcGVydGllcyBPcHRpb25hbCBtYXhpbXVtIG51bWJlciBvZiBwcm9wZXJ0aWVzL2VsZW1lbnRzIGluY2x1ZGVkIGluIGFueSBzaW5nbGUgb2JqZWN0L2FycmF5CiAqIEBwYXJhbSBtZW1vIE9wdGlvbmFsIE1lbW8gY2xhc3MgaGFuZGxpbmcgZGVjeWNsaW5nCiAqLwpmdW5jdGlvbiB2aXNpdCgKICBrZXksCiAgdmFsdWUsCiAgZGVwdGggPSArSW5maW5pdHksCiAgbWF4UHJvcGVydGllcyA9ICtJbmZpbml0eSwKICBtZW1vID0gbWVtb0J1aWxkZXIoKSwKKSB7CiAgY29uc3QgW21lbW9pemUsIHVubWVtb2l6ZV0gPSBtZW1vOwoKICAvLyBHZXQgdGhlIHNpbXBsZSBjYXNlcyBvdXQgb2YgdGhlIHdheSBmaXJzdAogIGlmICgKICAgIHZhbHVlID09IG51bGwgfHwgLy8gdGhpcyBtYXRjaGVzIG51bGwgYW5kIHVuZGVmaW5lZCAtPiBlcWVxIG5vdCBlcWVxZXEKICAgIChbJ251bWJlcicsICdib29sZWFuJywgJ3N0cmluZyddLmluY2x1ZGVzKHR5cGVvZiB2YWx1ZSkgJiYgIU51bWJlci5pc05hTih2YWx1ZSkpCiAgKSB7CiAgICByZXR1cm4gdmFsdWUgOwogIH0KCiAgY29uc3Qgc3RyaW5naWZpZWQgPSBzdHJpbmdpZnlWYWx1ZShrZXksIHZhbHVlKTsKCiAgLy8gQW55dGhpbmcgd2UgY291bGQgcG90ZW50aWFsbHkgZGlnIGludG8gbW9yZSAob2JqZWN0cyBvciBhcnJheXMpIHdpbGwgaGF2ZSBjb21lIGJhY2sgYXMgYCJbb2JqZWN0IFhYWFhdImAuCiAgLy8gRXZlcnl0aGluZyBlbHNlIHdpbGwgaGF2ZSBhbHJlYWR5IGJlZW4gc2VyaWFsaXplZCwgc28gaWYgd2UgZG9uJ3Qgc2VlIHRoYXQgcGF0dGVybiwgd2UncmUgZG9uZS4KICBpZiAoIXN0cmluZ2lmaWVkLnN0YXJ0c1dpdGgoJ1tvYmplY3QgJykpIHsKICAgIHJldHVybiBzdHJpbmdpZmllZDsKICB9CgogIC8vIEZyb20gaGVyZSBvbiwgd2UgY2FuIGFzc2VydCB0aGF0IGB2YWx1ZWAgaXMgZWl0aGVyIGFuIG9iamVjdCBvciBhbiBhcnJheS4KCiAgLy8gRG8gbm90IG5vcm1hbGl6ZSBvYmplY3RzIHRoYXQgd2Uga25vdyBoYXZlIGFscmVhZHkgYmVlbiBub3JtYWxpemVkLiBBcyBhIGdlbmVyYWwgcnVsZSwgdGhlCiAgLy8gIl9fc2VudHJ5X3NraXBfbm9ybWFsaXphdGlvbl9fIiBwcm9wZXJ0eSBzaG91bGQgb25seSBiZSB1c2VkIHNwYXJpbmdseSBhbmQgb25seSBzaG91bGQgb25seSBiZSBzZXQgb24gb2JqZWN0cyB0aGF0CiAgLy8gaGF2ZSBhbHJlYWR5IGJlZW4gbm9ybWFsaXplZC4KICBpZiAoKHZhbHVlIClbJ19fc2VudHJ5X3NraXBfbm9ybWFsaXphdGlvbl9fJ10pIHsKICAgIHJldHVybiB2YWx1ZSA7CiAgfQoKICAvLyBXZSBjYW4gc2V0IGBfX3NlbnRyeV9vdmVycmlkZV9ub3JtYWxpemF0aW9uX2RlcHRoX19gIG9uIGFuIG9iamVjdCB0byBlbnN1cmUgdGhhdCBmcm9tIHRoZXJlCiAgLy8gV2Uga2VlcCBhIGNlcnRhaW4gYW1vdW50IG9mIGRlcHRoLgogIC8vIFRoaXMgc2hvdWxkIGJlIHVzZWQgc3BhcmluZ2x5LCBlLmcuIHdlIHVzZSBpdCBmb3IgdGhlIHJlZHV4IGludGVncmF0aW9uIHRvIGVuc3VyZSB3ZSBnZXQgYSBjZXJ0YWluIGFtb3VudCBvZiBzdGF0ZS4KICBjb25zdCByZW1haW5pbmdEZXB0aCA9CiAgICB0eXBlb2YgKHZhbHVlIClbJ19fc2VudHJ5X292ZXJyaWRlX25vcm1hbGl6YXRpb25fZGVwdGhfXyddID09PSAnbnVtYmVyJwogICAgICA/ICgodmFsdWUgKVsnX19zZW50cnlfb3ZlcnJpZGVfbm9ybWFsaXphdGlvbl9kZXB0aF9fJ10gKQogICAgICA6IGRlcHRoOwoKICAvLyBXZSdyZSBhbHNvIGRvbmUgaWYgd2UndmUgcmVhY2hlZCB0aGUgbWF4IGRlcHRoCiAgaWYgKHJlbWFpbmluZ0RlcHRoID09PSAwKSB7CiAgICAvLyBBdCB0aGlzIHBvaW50IHdlIGtub3cgYHNlcmlhbGl6ZWRgIGlzIGEgc3RyaW5nIG9mIHRoZSBmb3JtIGAiW29iamVjdCBYWFhYXSJgLiBDbGVhbiBpdCB1cCBzbyBpdCdzIGp1c3QgYCJbWFhYWF0iYC4KICAgIHJldHVybiBzdHJpbmdpZmllZC5yZXBsYWNlKCdvYmplY3QgJywgJycpOwogIH0KCiAgLy8gSWYgd2UndmUgYWxyZWFkeSB2aXNpdGVkIHRoaXMgYnJhbmNoLCBiYWlsIG91dCwgYXMgaXQncyBjaXJjdWxhciByZWZlcmVuY2UuIElmIG5vdCwgbm90ZSB0aGF0IHdlJ3JlIHNlZWluZyBpdCBub3cuCiAgaWYgKG1lbW9pemUodmFsdWUpKSB7CiAgICByZXR1cm4gJ1tDaXJjdWxhciB+XSc7CiAgfQoKICAvLyBJZiB0aGUgdmFsdWUgaGFzIGEgYHRvSlNPTmAgbWV0aG9kLCB3ZSBjYWxsIGl0IHRvIGV4dHJhY3QgbW9yZSBpbmZvcm1hdGlvbgogIGNvbnN0IHZhbHVlV2l0aFRvSlNPTiA9IHZhbHVlIDsKICBpZiAodmFsdWVXaXRoVG9KU09OICYmIHR5cGVvZiB2YWx1ZVdpdGhUb0pTT04udG9KU09OID09PSAnZnVuY3Rpb24nKSB7CiAgICB0cnkgewogICAgICBjb25zdCBqc29uVmFsdWUgPSB2YWx1ZVdpdGhUb0pTT04udG9KU09OKCk7CiAgICAgIC8vIFdlIG5lZWQgdG8gbm9ybWFsaXplIHRoZSByZXR1cm4gdmFsdWUgb2YgYC50b0pTT04oKWAgaW4gY2FzZSBpdCBoYXMgY2lyY3VsYXIgcmVmZXJlbmNlcwogICAgICByZXR1cm4gdmlzaXQoJycsIGpzb25WYWx1ZSwgcmVtYWluaW5nRGVwdGggLSAxLCBtYXhQcm9wZXJ0aWVzLCBtZW1vKTsKICAgIH0gY2F0Y2ggKGVycikgewogICAgICAvLyBwYXNzIChUaGUgYnVpbHQtaW4gYHRvSlNPTmAgZmFpbGVkLCBidXQgd2UgY2FuIHN0aWxsIHRyeSB0byBkbyBpdCBvdXJzZWx2ZXMpCiAgICB9CiAgfQoKICAvLyBBdCB0aGlzIHBvaW50IHdlIGtub3cgd2UgZWl0aGVyIGhhdmUgYW4gb2JqZWN0IG9yIGFuIGFycmF5LCB3ZSBoYXZlbid0IHNlZW4gaXQgYmVmb3JlLCBhbmQgd2UncmUgZ29pbmcgdG8gcmVjdXJzZQogIC8vIGJlY2F1c2Ugd2UgaGF2ZW4ndCB5ZXQgcmVhY2hlZCB0aGUgbWF4IGRlcHRoLiBDcmVhdGUgYW4gYWNjdW11bGF0b3IgdG8gaG9sZCB0aGUgcmVzdWx0cyBvZiB2aXNpdGluZyBlYWNoCiAgLy8gcHJvcGVydHkvZW50cnksIGFuZCBrZWVwIHRyYWNrIG9mIHRoZSBudW1iZXIgb2YgaXRlbXMgd2UgYWRkIHRvIGl0LgogIGNvbnN0IG5vcm1hbGl6ZWQgPSAoQXJyYXkuaXNBcnJheSh2YWx1ZSkgPyBbXSA6IHt9KSA7CiAgbGV0IG51bUFkZGVkID0gMDsKCiAgLy8gQmVmb3JlIHdlIGJlZ2luLCBjb252ZXJ0YEVycm9yYCBhbmRgRXZlbnRgIGluc3RhbmNlcyBpbnRvIHBsYWluIG9iamVjdHMsIHNpbmNlIHNvbWUgb2YgZWFjaCBvZiB0aGVpciByZWxldmFudAogIC8vIHByb3BlcnRpZXMgYXJlIG5vbi1lbnVtZXJhYmxlIGFuZCBvdGhlcndpc2Ugd291bGQgZ2V0IG1pc3NlZC4KICBjb25zdCB2aXNpdGFibGUgPSBjb252ZXJ0VG9QbGFpbk9iamVjdCh2YWx1ZSApOwoKICBmb3IgKGNvbnN0IHZpc2l0S2V5IGluIHZpc2l0YWJsZSkgewogICAgLy8gQXZvaWQgaXRlcmF0aW5nIG92ZXIgZmllbGRzIGluIHRoZSBwcm90b3R5cGUgaWYgdGhleSd2ZSBzb21laG93IGJlZW4gZXhwb3NlZCB0byBlbnVtZXJhdGlvbi4KICAgIGlmICghT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHZpc2l0YWJsZSwgdmlzaXRLZXkpKSB7CiAgICAgIGNvbnRpbnVlOwogICAgfQoKICAgIGlmIChudW1BZGRlZCA+PSBtYXhQcm9wZXJ0aWVzKSB7CiAgICAgIG5vcm1hbGl6ZWRbdmlzaXRLZXldID0gJ1tNYXhQcm9wZXJ0aWVzIH5dJzsKICAgICAgYnJlYWs7CiAgICB9CgogICAgLy8gUmVjdXJzaXZlbHkgdmlzaXQgYWxsIHRoZSBjaGlsZCBub2RlcwogICAgY29uc3QgdmlzaXRWYWx1ZSA9IHZpc2l0YWJsZVt2aXNpdEtleV07CiAgICBub3JtYWxpemVkW3Zpc2l0S2V5XSA9IHZpc2l0KHZpc2l0S2V5LCB2aXNpdFZhbHVlLCByZW1haW5pbmdEZXB0aCAtIDEsIG1heFByb3BlcnRpZXMsIG1lbW8pOwoKICAgIG51bUFkZGVkKys7CiAgfQoKICAvLyBPbmNlIHdlJ3ZlIHZpc2l0ZWQgYWxsIHRoZSBicmFuY2hlcywgcmVtb3ZlIHRoZSBwYXJlbnQgZnJvbSBtZW1vIHN0b3JhZ2UKICB1bm1lbW9pemUodmFsdWUpOwoKICAvLyBSZXR1cm4gYWNjdW11bGF0ZWQgdmFsdWVzCiAgcmV0dXJuIG5vcm1hbGl6ZWQ7Cn0KCi8qIGVzbGludC1kaXNhYmxlIGNvbXBsZXhpdHkgKi8KLyoqCiAqIFN0cmluZ2lmeSB0aGUgZ2l2ZW4gdmFsdWUuIEhhbmRsZXMgdmFyaW91cyBrbm93biBzcGVjaWFsIHZhbHVlcyBhbmQgdHlwZXMuCiAqCiAqIE5vdCBtZWFudCB0byBiZSB1c2VkIG9uIHNpbXBsZSBwcmltaXRpdmVzIHdoaWNoIGFscmVhZHkgaGF2ZSBhIHN0cmluZyByZXByZXNlbnRhdGlvbiwgYXMgaXQgd2lsbCwgZm9yIGV4YW1wbGUsIHR1cm4KICogdGhlIG51bWJlciAxMjMxIGludG8gIltPYmplY3QgTnVtYmVyXSIsIG5vciBvbiBgbnVsbGAsIGFzIGl0IHdpbGwgdGhyb3cuCiAqCiAqIEBwYXJhbSB2YWx1ZSBUaGUgdmFsdWUgdG8gc3RyaW5naWZ5CiAqIEByZXR1cm5zIEEgc3RyaW5naWZpZWQgcmVwcmVzZW50YXRpb24gb2YgdGhlIGdpdmVuIHZhbHVlCiAqLwpmdW5jdGlvbiBzdHJpbmdpZnlWYWx1ZSgKICBrZXksCiAgLy8gdGhpcyB0eXBlIGlzIGEgdGlueSBiaXQgb2YgYSBjaGVhdCwgc2luY2UgdGhpcyBmdW5jdGlvbiBkb2VzIGhhbmRsZSBOYU4gKHdoaWNoIGlzIHRlY2huaWNhbGx5IGEgbnVtYmVyKSwgYnV0IGZvcgogIC8vIG91ciBpbnRlcm5hbCB1c2UsIGl0J2xsIGRvCiAgdmFsdWUsCikgewogIHRyeSB7CiAgICBpZiAoa2V5ID09PSAnZG9tYWluJyAmJiB2YWx1ZSAmJiB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnICYmICh2YWx1ZSApLl9ldmVudHMpIHsKICAgICAgcmV0dXJuICdbRG9tYWluXSc7CiAgICB9CgogICAgaWYgKGtleSA9PT0gJ2RvbWFpbkVtaXR0ZXInKSB7CiAgICAgIHJldHVybiAnW0RvbWFpbkVtaXR0ZXJdJzsKICAgIH0KCiAgICAvLyBJdCdzIHNhZmUgdG8gdXNlIGBnbG9iYWxgLCBgd2luZG93YCwgYW5kIGBkb2N1bWVudGAgaGVyZSBpbiB0aGlzIG1hbm5lciwgYXMgd2UgYXJlIGFzc2VydGluZyB1c2luZyBgdHlwZW9mYCBmaXJzdAogICAgLy8gd2hpY2ggd29uJ3QgdGhyb3cgaWYgdGhleSBhcmUgbm90IHByZXNlbnQuCgogICAgaWYgKHR5cGVvZiBnbG9iYWwgIT09ICd1bmRlZmluZWQnICYmIHZhbHVlID09PSBnbG9iYWwpIHsKICAgICAgcmV0dXJuICdbR2xvYmFsXSc7CiAgICB9CgogICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLXJlc3RyaWN0ZWQtZ2xvYmFscwogICAgaWYgKHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnICYmIHZhbHVlID09PSB3aW5kb3cpIHsKICAgICAgcmV0dXJuICdbV2luZG93XSc7CiAgICB9CgogICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLXJlc3RyaWN0ZWQtZ2xvYmFscwogICAgaWYgKHR5cGVvZiBkb2N1bWVudCAhPT0gJ3VuZGVmaW5lZCcgJiYgdmFsdWUgPT09IGRvY3VtZW50KSB7CiAgICAgIHJldHVybiAnW0RvY3VtZW50XSc7CiAgICB9CgogICAgaWYgKGlzVnVlVmlld01vZGVsKHZhbHVlKSkgewogICAgICByZXR1cm4gJ1tWdWVWaWV3TW9kZWxdJzsKICAgIH0KCiAgICAvLyBSZWFjdCdzIFN5bnRoZXRpY0V2ZW50IHRoaW5neQogICAgaWYgKGlzU3ludGhldGljRXZlbnQodmFsdWUpKSB7CiAgICAgIHJldHVybiAnW1N5bnRoZXRpY0V2ZW50XSc7CiAgICB9CgogICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ251bWJlcicgJiYgdmFsdWUgIT09IHZhbHVlKSB7CiAgICAgIHJldHVybiAnW05hTl0nOwogICAgfQoKICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdmdW5jdGlvbicpIHsKICAgICAgcmV0dXJuIGBbRnVuY3Rpb246ICR7Z2V0RnVuY3Rpb25OYW1lKHZhbHVlKX1dYDsKICAgIH0KCiAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnc3ltYm9sJykgewogICAgICByZXR1cm4gYFske1N0cmluZyh2YWx1ZSl9XWA7CiAgICB9CgogICAgLy8gc3RyaW5naWZpZWQgQmlnSW50cyBhcmUgaW5kaXN0aW5ndWlzaGFibGUgZnJvbSByZWd1bGFyIG51bWJlcnMsIHNvIHdlIG5lZWQgdG8gbGFiZWwgdGhlbSB0byBhdm9pZCBjb25mdXNpb24KICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdiaWdpbnQnKSB7CiAgICAgIHJldHVybiBgW0JpZ0ludDogJHtTdHJpbmcodmFsdWUpfV1gOwogICAgfQoKICAgIC8vIE5vdyB0aGF0IHdlJ3ZlIGtub2NrZWQgb3V0IGFsbCB0aGUgc3BlY2lhbCBjYXNlcyBhbmQgdGhlIHByaW1pdGl2ZXMsIGFsbCB3ZSBoYXZlIGxlZnQgYXJlIG9iamVjdHMuIFNpbXBseSBjYXN0aW5nCiAgICAvLyB0aGVtIHRvIHN0cmluZ3MgbWVhbnMgdGhhdCBpbnN0YW5jZXMgb2YgY2xhc3NlcyB3aGljaCBoYXZlbid0IGRlZmluZWQgdGhlaXIgYHRvU3RyaW5nVGFnYCB3aWxsIGp1c3QgY29tZSBvdXQgYXMKICAgIC8vIGAiW29iamVjdCBPYmplY3RdImAuIElmIHdlIGluc3RlYWQgbG9vayBhdCB0aGUgY29uc3RydWN0b3IncyBuYW1lICh3aGljaCBpcyB0aGUgc2FtZSBhcyB0aGUgbmFtZSBvZiB0aGUgY2xhc3MpLAogICAgLy8gd2UgY2FuIG1ha2Ugc3VyZSB0aGF0IG9ubHkgcGxhaW4gb2JqZWN0cyBjb21lIG91dCB0aGF0IHdheS4KICAgIGNvbnN0IG9iak5hbWUgPSBnZXRDb25zdHJ1Y3Rvck5hbWUodmFsdWUpOwoKICAgIC8vIEhhbmRsZSBIVE1MIEVsZW1lbnRzCiAgICBpZiAoL15IVE1MKFx3KilFbGVtZW50JC8udGVzdChvYmpOYW1lKSkgewogICAgICByZXR1cm4gYFtIVE1MRWxlbWVudDogJHtvYmpOYW1lfV1gOwogICAgfQoKICAgIHJldHVybiBgW29iamVjdCAke29iak5hbWV9XWA7CiAgfSBjYXRjaCAoZXJyKSB7CiAgICByZXR1cm4gYCoqbm9uLXNlcmlhbGl6YWJsZSoqICgke2Vycn0pYDsKICB9Cn0KLyogZXNsaW50LWVuYWJsZSBjb21wbGV4aXR5ICovCgpmdW5jdGlvbiBnZXRDb25zdHJ1Y3Rvck5hbWUodmFsdWUpIHsKICBjb25zdCBwcm90b3R5cGUgPSBPYmplY3QuZ2V0UHJvdG90eXBlT2YodmFsdWUpOwoKICByZXR1cm4gcHJvdG90eXBlID8gcHJvdG90eXBlLmNvbnN0cnVjdG9yLm5hbWUgOiAnbnVsbCBwcm90b3R5cGUnOwp9CgovKioKICogTm9ybWFsaXplcyBVUkxzIGluIGV4Y2VwdGlvbnMgYW5kIHN0YWNrdHJhY2VzIHRvIGEgYmFzZSBwYXRoIHNvIFNlbnRyeSBjYW4gZmluZ2VycHJpbnQKICogYWNyb3NzIHBsYXRmb3JtcyBhbmQgd29ya2luZyBkaXJlY3RvcnkuCiAqCiAqIEBwYXJhbSB1cmwgVGhlIFVSTCB0byBiZSBub3JtYWxpemVkLgogKiBAcGFyYW0gYmFzZVBhdGggVGhlIGFwcGxpY2F0aW9uIGJhc2UgcGF0aC4KICogQHJldHVybnMgVGhlIG5vcm1hbGl6ZWQgVVJMLgogKi8KZnVuY3Rpb24gbm9ybWFsaXplVXJsVG9CYXNlKHVybCwgYmFzZVBhdGgpIHsKICBjb25zdCBlc2NhcGVkQmFzZSA9IGJhc2VQYXRoCiAgICAvLyBCYWNrc2xhc2ggdG8gZm9yd2FyZAogICAgLnJlcGxhY2UoL1xcL2csICcvJykKICAgIC8vIEVzY2FwZSBSZWdFeHAgc3BlY2lhbCBjaGFyYWN0ZXJzCiAgICAucmVwbGFjZSgvW3xcXHt9KClbXF1eJCsqPy5dL2csICdcXCQmJyk7CgogIGxldCBuZXdVcmwgPSB1cmw7CiAgdHJ5IHsKICAgIG5ld1VybCA9IGRlY29kZVVSSSh1cmwpOwogIH0gY2F0Y2ggKF9PbykgewogICAgLy8gU29tZXRpbWUgdGhpcyBicmVha3MKICB9CiAgcmV0dXJuICgKICAgIG5ld1VybAogICAgICAucmVwbGFjZSgvXFwvZywgJy8nKQogICAgICAucmVwbGFjZSgvd2VicGFjazpcLz8vZywgJycpIC8vIFJlbW92ZSBpbnRlcm1lZGlhdGUgYmFzZSBwYXRoCiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAc2VudHJ5LWludGVybmFsL3Nkay9uby1yZWdleHAtY29uc3RydWN0b3IKICAgICAgLnJlcGxhY2UobmV3IFJlZ0V4cChgKGZpbGU6Ly8pPy8qJHtlc2NhcGVkQmFzZX0vKmAsICdpZycpLCAnYXBwOi8vLycpCiAgKTsKfQoKLy8gU2xpZ2h0bHkgbW9kaWZpZWQgKG5vIElFOCBzdXBwb3J0LCBFUzYpIGFuZCB0cmFuc2NyaWJlZCB0byBUeXBlU2NyaXB0Ci8vIGh0dHBzOi8vZ2l0aHViLmNvbS9jYWx2aW5tZXRjYWxmL3JvbGx1cC1wbHVnaW4tbm9kZS1idWlsdGlucy9ibG9iLzYzYWI4YWFjZDAxMzc2NzQ0NWNhMjk5ZTQ2OGQ5YTYwYTk1MzI4ZDcvc3JjL2VzNi9wYXRoLmpzCi8vCi8vIENvcHlyaWdodCBKb3llbnQsIEluYy5hbmQgb3RoZXIgTm9kZSBjb250cmlidXRvcnMuCi8vCi8vIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhCi8vIGNvcHkgb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGUKLy8gIlNvZnR3YXJlIiksIHRvIGRlYWwgaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZwovLyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0cyB0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsCi8vIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vciBzZWxsIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQKLy8gcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpcyBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlCi8vIGZvbGxvd2luZyBjb25kaXRpb25zOgovLwovLyBUaGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSBzaGFsbCBiZSBpbmNsdWRlZAovLyBpbiBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS4KLy8KLy8gVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEICJBUyBJUyIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsIEVYUFJFU1MKLy8gT1IgSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRgovLyBNRVJDSEFOVEFCSUxJVFksIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOCi8vIE5PIEVWRU5UIFNIQUxMIFRIRSBBVVRIT1JTIE9SIENPUFlSSUdIVCBIT0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLAovLyBEQU1BR0VTIE9SIE9USEVSIExJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IKLy8gT1RIRVJXSVNFLCBBUklTSU5HIEZST00sIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRQovLyBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU4gVEhFIFNPRlRXQVJFLgoKCi8vIFNwbGl0IGEgZmlsZW5hbWUgaW50byBbcm9vdCwgZGlyLCBiYXNlbmFtZSwgZXh0XSwgdW5peCB2ZXJzaW9uCi8vICdyb290JyBpcyBqdXN0IGEgc2xhc2gsIG9yIG5vdGhpbmcuCmNvbnN0IHNwbGl0UGF0aFJlID0gL14oXFMrOlxcfFwvPykoW1xzXFNdKj8pKCg/OlwuezEsMn18W14vXFxdKz98KShcLlteLi9cXF0qfCkpKD86Wy9cXF0qKSQvOwovKiogSlNEb2MgKi8KZnVuY3Rpb24gc3BsaXRQYXRoKGZpbGVuYW1lKSB7CiAgLy8gVHJ1bmNhdGUgZmlsZXMgbmFtZXMgZ3JlYXRlciB0aGFuIDEwMjQgY2hhcmFjdGVycyB0byBhdm9pZCByZWdleCBkb3MKICAvLyBodHRwczovL2dpdGh1Yi5jb20vZ2V0c2VudHJ5L3NlbnRyeS1qYXZhc2NyaXB0L3B1bGwvODczNyNkaXNjdXNzaW9uX3IxMjg1NzE5MTcyCiAgY29uc3QgdHJ1bmNhdGVkID0gZmlsZW5hbWUubGVuZ3RoID4gMTAyNCA/IGA8dHJ1bmNhdGVkPiR7ZmlsZW5hbWUuc2xpY2UoLTEwMjQpfWAgOiBmaWxlbmFtZTsKICBjb25zdCBwYXJ0cyA9IHNwbGl0UGF0aFJlLmV4ZWModHJ1bmNhdGVkKTsKICByZXR1cm4gcGFydHMgPyBwYXJ0cy5zbGljZSgxKSA6IFtdOwp9CgovKiogSlNEb2MgKi8KZnVuY3Rpb24gZGlybmFtZShwYXRoKSB7CiAgY29uc3QgcmVzdWx0ID0gc3BsaXRQYXRoKHBhdGgpOwogIGNvbnN0IHJvb3QgPSByZXN1bHRbMF07CiAgbGV0IGRpciA9IHJlc3VsdFsxXTsKCiAgaWYgKCFyb290ICYmICFkaXIpIHsKICAgIC8vIE5vIGRpcm5hbWUgd2hhdHNvZXZlcgogICAgcmV0dXJuICcuJzsKICB9CgogIGlmIChkaXIpIHsKICAgIC8vIEl0IGhhcyBhIGRpcm5hbWUsIHN0cmlwIHRyYWlsaW5nIHNsYXNoCiAgICBkaXIgPSBkaXIuc2xpY2UoMCwgZGlyLmxlbmd0aCAtIDEpOwogIH0KCiAgcmV0dXJuIHJvb3QgKyBkaXI7Cn0KCi8qIGVzbGludC1kaXNhYmxlIEB0eXBlc2NyaXB0LWVzbGludC9leHBsaWNpdC1mdW5jdGlvbi1yZXR1cm4tdHlwZSAqLwovKiBlc2xpbnQtZGlzYWJsZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55ICovCgovKiogU3luY1Byb21pc2UgaW50ZXJuYWwgc3RhdGVzICovCnZhciBTdGF0ZXM7IChmdW5jdGlvbiAoU3RhdGVzKSB7CiAgLyoqIFBlbmRpbmcgKi8KICBjb25zdCBQRU5ESU5HID0gMDsgU3RhdGVzW1N0YXRlc1siUEVORElORyJdID0gUEVORElOR10gPSAiUEVORElORyI7CiAgLyoqIFJlc29sdmVkIC8gT0sgKi8KICBjb25zdCBSRVNPTFZFRCA9IDE7IFN0YXRlc1tTdGF0ZXNbIlJFU09MVkVEIl0gPSBSRVNPTFZFRF0gPSAiUkVTT0xWRUQiOwogIC8qKiBSZWplY3RlZCAvIEVycm9yICovCiAgY29uc3QgUkVKRUNURUQgPSAyOyBTdGF0ZXNbU3RhdGVzWyJSRUpFQ1RFRCJdID0gUkVKRUNURURdID0gIlJFSkVDVEVEIjsKfSkoU3RhdGVzIHx8IChTdGF0ZXMgPSB7fSkpOwoKLy8gT3ZlcmxvYWRzIHNvIHdlIGNhbiBjYWxsIHJlc29sdmVkU3luY1Byb21pc2Ugd2l0aG91dCBhcmd1bWVudHMgYW5kIGdlbmVyaWMgYXJndW1lbnQKCi8qKgogKiBDcmVhdGVzIGEgcmVzb2x2ZWQgc3luYyBwcm9taXNlLgogKgogKiBAcGFyYW0gdmFsdWUgdGhlIHZhbHVlIHRvIHJlc29sdmUgdGhlIHByb21pc2Ugd2l0aAogKiBAcmV0dXJucyB0aGUgcmVzb2x2ZWQgc3luYyBwcm9taXNlCiAqLwpmdW5jdGlvbiByZXNvbHZlZFN5bmNQcm9taXNlKHZhbHVlKSB7CiAgcmV0dXJuIG5ldyBTeW5jUHJvbWlzZShyZXNvbHZlID0+IHsKICAgIHJlc29sdmUodmFsdWUpOwogIH0pOwp9CgovKioKICogQ3JlYXRlcyBhIHJlamVjdGVkIHN5bmMgcHJvbWlzZS4KICoKICogQHBhcmFtIHZhbHVlIHRoZSB2YWx1ZSB0byByZWplY3QgdGhlIHByb21pc2Ugd2l0aAogKiBAcmV0dXJucyB0aGUgcmVqZWN0ZWQgc3luYyBwcm9taXNlCiAqLwpmdW5jdGlvbiByZWplY3RlZFN5bmNQcm9taXNlKHJlYXNvbikgewogIHJldHVybiBuZXcgU3luY1Byb21pc2UoKF8sIHJlamVjdCkgPT4gewogICAgcmVqZWN0KHJlYXNvbik7CiAgfSk7Cn0KCi8qKgogKiBUaGVuYWJsZSBjbGFzcyB0aGF0IGJlaGF2ZXMgbGlrZSBhIFByb21pc2UgYW5kIGZvbGxvd3MgaXQncyBpbnRlcmZhY2UKICogYnV0IGlzIG5vdCBhc3luYyBpbnRlcm5hbGx5CiAqLwpjbGFzcyBTeW5jUHJvbWlzZSB7CgogICBjb25zdHJ1Y3RvcigKICAgIGV4ZWN1dG9yLAogICkge1N5bmNQcm9taXNlLnByb3RvdHlwZS5fX2luaXQuY2FsbCh0aGlzKTtTeW5jUHJvbWlzZS5wcm90b3R5cGUuX19pbml0Mi5jYWxsKHRoaXMpO1N5bmNQcm9taXNlLnByb3RvdHlwZS5fX2luaXQzLmNhbGwodGhpcyk7U3luY1Byb21pc2UucHJvdG90eXBlLl9faW5pdDQuY2FsbCh0aGlzKTsKICAgIHRoaXMuX3N0YXRlID0gU3RhdGVzLlBFTkRJTkc7CiAgICB0aGlzLl9oYW5kbGVycyA9IFtdOwoKICAgIHRyeSB7CiAgICAgIGV4ZWN1dG9yKHRoaXMuX3Jlc29sdmUsIHRoaXMuX3JlamVjdCk7CiAgICB9IGNhdGNoIChlKSB7CiAgICAgIHRoaXMuX3JlamVjdChlKTsKICAgIH0KICB9CgogIC8qKiBKU0RvYyAqLwogICB0aGVuKAogICAgb25mdWxmaWxsZWQsCiAgICBvbnJlamVjdGVkLAogICkgewogICAgcmV0dXJuIG5ldyBTeW5jUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7CiAgICAgIHRoaXMuX2hhbmRsZXJzLnB1c2goWwogICAgICAgIGZhbHNlLAogICAgICAgIHJlc3VsdCA9PiB7CiAgICAgICAgICBpZiAoIW9uZnVsZmlsbGVkKSB7CiAgICAgICAgICAgIC8vIFRPRE86IMKvXF8o44OEKV8vwq8KICAgICAgICAgICAgLy8gVE9ETzogRklYTUUKICAgICAgICAgICAgcmVzb2x2ZShyZXN1bHQgKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgICAgcmVzb2x2ZShvbmZ1bGZpbGxlZChyZXN1bHQpKTsKICAgICAgICAgICAgfSBjYXRjaCAoZSkgewogICAgICAgICAgICAgIHJlamVjdChlKTsKICAgICAgICAgICAgfQogICAgICAgICAgfQogICAgICAgIH0sCiAgICAgICAgcmVhc29uID0+IHsKICAgICAgICAgIGlmICghb25yZWplY3RlZCkgewogICAgICAgICAgICByZWplY3QocmVhc29uKTsKICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgICAgcmVzb2x2ZShvbnJlamVjdGVkKHJlYXNvbikpOwogICAgICAgICAgICB9IGNhdGNoIChlKSB7CiAgICAgICAgICAgICAgcmVqZWN0KGUpOwogICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgfSwKICAgICAgXSk7CiAgICAgIHRoaXMuX2V4ZWN1dGVIYW5kbGVycygpOwogICAgfSk7CiAgfQoKICAvKiogSlNEb2MgKi8KICAgY2F0Y2goCiAgICBvbnJlamVjdGVkLAogICkgewogICAgcmV0dXJuIHRoaXMudGhlbih2YWwgPT4gdmFsLCBvbnJlamVjdGVkKTsKICB9CgogIC8qKiBKU0RvYyAqLwogICBmaW5hbGx5KG9uZmluYWxseSkgewogICAgcmV0dXJuIG5ldyBTeW5jUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7CiAgICAgIGxldCB2YWw7CiAgICAgIGxldCBpc1JlamVjdGVkOwoKICAgICAgcmV0dXJuIHRoaXMudGhlbigKICAgICAgICB2YWx1ZSA9PiB7CiAgICAgICAgICBpc1JlamVjdGVkID0gZmFsc2U7CiAgICAgICAgICB2YWwgPSB2YWx1ZTsKICAgICAgICAgIGlmIChvbmZpbmFsbHkpIHsKICAgICAgICAgICAgb25maW5hbGx5KCk7CiAgICAgICAgICB9CiAgICAgICAgfSwKICAgICAgICByZWFzb24gPT4gewogICAgICAgICAgaXNSZWplY3RlZCA9IHRydWU7CiAgICAgICAgICB2YWwgPSByZWFzb247CiAgICAgICAgICBpZiAob25maW5hbGx5KSB7CiAgICAgICAgICAgIG9uZmluYWxseSgpOwogICAgICAgICAgfQogICAgICAgIH0sCiAgICAgICkudGhlbigoKSA9PiB7CiAgICAgICAgaWYgKGlzUmVqZWN0ZWQpIHsKICAgICAgICAgIHJlamVjdCh2YWwpOwogICAgICAgICAgcmV0dXJuOwogICAgICAgIH0KCiAgICAgICAgcmVzb2x2ZSh2YWwgKTsKICAgICAgfSk7CiAgICB9KTsKICB9CgogIC8qKiBKU0RvYyAqLwogICAgX19pbml0KCkge3RoaXMuX3Jlc29sdmUgPSAodmFsdWUpID0+IHsKICAgIHRoaXMuX3NldFJlc3VsdChTdGF0ZXMuUkVTT0xWRUQsIHZhbHVlKTsKICB9O30KCiAgLyoqIEpTRG9jICovCiAgICBfX2luaXQyKCkge3RoaXMuX3JlamVjdCA9IChyZWFzb24pID0+IHsKICAgIHRoaXMuX3NldFJlc3VsdChTdGF0ZXMuUkVKRUNURUQsIHJlYXNvbik7CiAgfTt9CgogIC8qKiBKU0RvYyAqLwogICAgX19pbml0MygpIHt0aGlzLl9zZXRSZXN1bHQgPSAoc3RhdGUsIHZhbHVlKSA9PiB7CiAgICBpZiAodGhpcy5fc3RhdGUgIT09IFN0YXRlcy5QRU5ESU5HKSB7CiAgICAgIHJldHVybjsKICAgIH0KCiAgICBpZiAoaXNUaGVuYWJsZSh2YWx1ZSkpIHsKICAgICAgdm9pZCAodmFsdWUgKS50aGVuKHRoaXMuX3Jlc29sdmUsIHRoaXMuX3JlamVjdCk7CiAgICAgIHJldHVybjsKICAgIH0KCiAgICB0aGlzLl9zdGF0ZSA9IHN0YXRlOwogICAgdGhpcy5fdmFsdWUgPSB2YWx1ZTsKCiAgICB0aGlzLl9leGVjdXRlSGFuZGxlcnMoKTsKICB9O30KCiAgLyoqIEpTRG9jICovCiAgICBfX2luaXQ0KCkge3RoaXMuX2V4ZWN1dGVIYW5kbGVycyA9ICgpID0+IHsKICAgIGlmICh0aGlzLl9zdGF0ZSA9PT0gU3RhdGVzLlBFTkRJTkcpIHsKICAgICAgcmV0dXJuOwogICAgfQoKICAgIGNvbnN0IGNhY2hlZEhhbmRsZXJzID0gdGhpcy5faGFuZGxlcnMuc2xpY2UoKTsKICAgIHRoaXMuX2hhbmRsZXJzID0gW107CgogICAgY2FjaGVkSGFuZGxlcnMuZm9yRWFjaChoYW5kbGVyID0+IHsKICAgICAgaWYgKGhhbmRsZXJbMF0pIHsKICAgICAgICByZXR1cm47CiAgICAgIH0KCiAgICAgIGlmICh0aGlzLl9zdGF0ZSA9PT0gU3RhdGVzLlJFU09MVkVEKSB7CiAgICAgICAgaGFuZGxlclsxXSh0aGlzLl92YWx1ZSApOwogICAgICB9CgogICAgICBpZiAodGhpcy5fc3RhdGUgPT09IFN0YXRlcy5SRUpFQ1RFRCkgewogICAgICAgIGhhbmRsZXJbMl0odGhpcy5fdmFsdWUpOwogICAgICB9CgogICAgICBoYW5kbGVyWzBdID0gdHJ1ZTsKICAgIH0pOwogIH07fQp9CgovKioKICogQ3JlYXRlcyBhbiBuZXcgUHJvbWlzZUJ1ZmZlciBvYmplY3Qgd2l0aCB0aGUgc3BlY2lmaWVkIGxpbWl0CiAqIEBwYXJhbSBsaW1pdCBtYXggbnVtYmVyIG9mIHByb21pc2VzIHRoYXQgY2FuIGJlIHN0b3JlZCBpbiB0aGUgYnVmZmVyCiAqLwpmdW5jdGlvbiBtYWtlUHJvbWlzZUJ1ZmZlcihsaW1pdCkgewogIGNvbnN0IGJ1ZmZlciA9IFtdOwoKICBmdW5jdGlvbiBpc1JlYWR5KCkgewogICAgcmV0dXJuIGxpbWl0ID09PSB1bmRlZmluZWQgfHwgYnVmZmVyLmxlbmd0aCA8IGxpbWl0OwogIH0KCiAgLyoqCiAgICogUmVtb3ZlIGEgcHJvbWlzZSBmcm9tIHRoZSBxdWV1ZS4KICAgKgogICAqIEBwYXJhbSB0YXNrIENhbiBiZSBhbnkgUHJvbWlzZUxpa2U8VD4KICAgKiBAcmV0dXJucyBSZW1vdmVkIHByb21pc2UuCiAgICovCiAgZnVuY3Rpb24gcmVtb3ZlKHRhc2spIHsKICAgIHJldHVybiBidWZmZXIuc3BsaWNlKGJ1ZmZlci5pbmRleE9mKHRhc2spLCAxKVswXTsKICB9CgogIC8qKgogICAqIEFkZCBhIHByb21pc2UgKHJlcHJlc2VudGluZyBhbiBpbi1mbGlnaHQgYWN0aW9uKSB0byB0aGUgcXVldWUsIGFuZCBzZXQgaXQgdG8gcmVtb3ZlIGl0c2VsZiBvbiBmdWxmaWxsbWVudC4KICAgKgogICAqIEBwYXJhbSB0YXNrUHJvZHVjZXIgQSBmdW5jdGlvbiBwcm9kdWNpbmcgYW55IFByb21pc2VMaWtlPFQ+OyBJbiBwcmV2aW91cyB2ZXJzaW9ucyB0aGlzIHVzZWQgdG8gYmUgYHRhc2s6CiAgICogICAgICAgIFByb21pc2VMaWtlPFQ+YCwgYnV0IHVuZGVyIHRoYXQgbW9kZWwsIFByb21pc2VzIHdlcmUgaW5zdGFudGx5IGNyZWF0ZWQgb24gdGhlIGNhbGwtc2l0ZSBhbmQgdGhlaXIgZXhlY3V0b3IKICAgKiAgICAgICAgZnVuY3Rpb25zIHRoZXJlZm9yZSByYW4gaW1tZWRpYXRlbHkuIFRodXMsIGV2ZW4gaWYgdGhlIGJ1ZmZlciB3YXMgZnVsbCwgdGhlIGFjdGlvbiBzdGlsbCBoYXBwZW5lZC4gQnkKICAgKiAgICAgICAgcmVxdWlyaW5nIHRoZSBwcm9taXNlIHRvIGJlIHdyYXBwZWQgaW4gYSBmdW5jdGlvbiwgd2UgY2FuIGRlZmVyIHByb21pc2UgY3JlYXRpb24gdW50aWwgYWZ0ZXIgdGhlIGJ1ZmZlcgogICAqICAgICAgICBsaW1pdCBjaGVjay4KICAgKiBAcmV0dXJucyBUaGUgb3JpZ2luYWwgcHJvbWlzZS4KICAgKi8KICBmdW5jdGlvbiBhZGQodGFza1Byb2R1Y2VyKSB7CiAgICBpZiAoIWlzUmVhZHkoKSkgewogICAgICByZXR1cm4gcmVqZWN0ZWRTeW5jUHJvbWlzZShuZXcgU2VudHJ5RXJyb3IoJ05vdCBhZGRpbmcgUHJvbWlzZSBiZWNhdXNlIGJ1ZmZlciBsaW1pdCB3YXMgcmVhY2hlZC4nKSk7CiAgICB9CgogICAgLy8gc3RhcnQgdGhlIHRhc2sgYW5kIGFkZCBpdHMgcHJvbWlzZSB0byB0aGUgcXVldWUKICAgIGNvbnN0IHRhc2sgPSB0YXNrUHJvZHVjZXIoKTsKICAgIGlmIChidWZmZXIuaW5kZXhPZih0YXNrKSA9PT0gLTEpIHsKICAgICAgYnVmZmVyLnB1c2godGFzayk7CiAgICB9CiAgICB2b2lkIHRhc2sKICAgICAgLnRoZW4oKCkgPT4gcmVtb3ZlKHRhc2spKQogICAgICAvLyBVc2UgYHRoZW4obnVsbCwgcmVqZWN0aW9uSGFuZGxlcilgIHJhdGhlciB0aGFuIGBjYXRjaChyZWplY3Rpb25IYW5kbGVyKWAgc28gdGhhdCB3ZSBjYW4gdXNlIGBQcm9taXNlTGlrZWAKICAgICAgLy8gcmF0aGVyIHRoYW4gYFByb21pc2VgLiBgUHJvbWlzZUxpa2VgIGRvZXNuJ3QgaGF2ZSBhIGAuY2F0Y2hgIG1ldGhvZCwgbWFraW5nIGl0cyBwb2x5ZmlsbCBzbWFsbGVyLiAoRVM1IGRpZG4ndAogICAgICAvLyBoYXZlIHByb21pc2VzLCBzbyBUUyBoYXMgdG8gcG9seWZpbGwgd2hlbiBkb3duLWNvbXBpbGluZy4pCiAgICAgIC50aGVuKG51bGwsICgpID0+CiAgICAgICAgcmVtb3ZlKHRhc2spLnRoZW4obnVsbCwgKCkgPT4gewogICAgICAgICAgLy8gV2UgaGF2ZSB0byBhZGQgYW5vdGhlciBjYXRjaCBoZXJlIGJlY2F1c2UgYHJlbW92ZSgpYCBzdGFydHMgYSBuZXcgcHJvbWlzZSBjaGFpbi4KICAgICAgICB9KSwKICAgICAgKTsKICAgIHJldHVybiB0YXNrOwogIH0KCiAgLyoqCiAgICogV2FpdCBmb3IgYWxsIHByb21pc2VzIGluIHRoZSBxdWV1ZSB0byByZXNvbHZlIG9yIGZvciB0aW1lb3V0IHRvIGV4cGlyZSwgd2hpY2hldmVyIGNvbWVzIGZpcnN0LgogICAqCiAgICogQHBhcmFtIHRpbWVvdXQgVGhlIHRpbWUsIGluIG1zLCBhZnRlciB3aGljaCB0byByZXNvbHZlIHRvIGBmYWxzZWAgaWYgdGhlIHF1ZXVlIGlzIHN0aWxsIG5vbi1lbXB0eS4gUGFzc2luZyBgMGAgKG9yCiAgICogbm90IHBhc3NpbmcgYW55dGhpbmcpIHdpbGwgbWFrZSB0aGUgcHJvbWlzZSB3YWl0IGFzIGxvbmcgYXMgaXQgdGFrZXMgZm9yIHRoZSBxdWV1ZSB0byBkcmFpbiBiZWZvcmUgcmVzb2x2aW5nIHRvCiAgICogYHRydWVgLgogICAqIEByZXR1cm5zIEEgcHJvbWlzZSB3aGljaCB3aWxsIHJlc29sdmUgdG8gYHRydWVgIGlmIHRoZSBxdWV1ZSBpcyBhbHJlYWR5IGVtcHR5IG9yIGRyYWlucyBiZWZvcmUgdGhlIHRpbWVvdXQsIGFuZAogICAqIGBmYWxzZWAgb3RoZXJ3aXNlCiAgICovCiAgZnVuY3Rpb24gZHJhaW4odGltZW91dCkgewogICAgcmV0dXJuIG5ldyBTeW5jUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7CiAgICAgIGxldCBjb3VudGVyID0gYnVmZmVyLmxlbmd0aDsKCiAgICAgIGlmICghY291bnRlcikgewogICAgICAgIHJldHVybiByZXNvbHZlKHRydWUpOwogICAgICB9CgogICAgICAvLyB3YWl0IGZvciBgdGltZW91dGAgbXMgYW5kIHRoZW4gcmVzb2x2ZSB0byBgZmFsc2VgIChpZiBub3QgY2FuY2VsbGVkIGZpcnN0KQogICAgICBjb25zdCBjYXB0dXJlZFNldFRpbWVvdXQgPSBzZXRUaW1lb3V0KCgpID0+IHsKICAgICAgICBpZiAodGltZW91dCAmJiB0aW1lb3V0ID4gMCkgewogICAgICAgICAgcmVzb2x2ZShmYWxzZSk7CiAgICAgICAgfQogICAgICB9LCB0aW1lb3V0KTsKCiAgICAgIC8vIGlmIGFsbCBwcm9taXNlcyByZXNvbHZlIGluIHRpbWUsIGNhbmNlbCB0aGUgdGltZXIgYW5kIHJlc29sdmUgdG8gYHRydWVgCiAgICAgIGJ1ZmZlci5mb3JFYWNoKGl0ZW0gPT4gewogICAgICAgIHZvaWQgcmVzb2x2ZWRTeW5jUHJvbWlzZShpdGVtKS50aGVuKCgpID0+IHsKICAgICAgICAgIGlmICghLS1jb3VudGVyKSB7CiAgICAgICAgICAgIGNsZWFyVGltZW91dChjYXB0dXJlZFNldFRpbWVvdXQpOwogICAgICAgICAgICByZXNvbHZlKHRydWUpOwogICAgICAgICAgfQogICAgICAgIH0sIHJlamVjdCk7CiAgICAgIH0pOwogICAgfSk7CiAgfQoKICByZXR1cm4gewogICAgJDogYnVmZmVyLAogICAgYWRkLAogICAgZHJhaW4sCiAgfTsKfQoKLyoqCiAqIERvZXMgdGhpcyBmaWxlbmFtZSBsb29rIGxpa2UgaXQncyBwYXJ0IG9mIHRoZSBhcHAgY29kZT8KICovCmZ1bmN0aW9uIGZpbGVuYW1lSXNJbkFwcChmaWxlbmFtZSwgaXNOYXRpdmUgPSBmYWxzZSkgewogIGNvbnN0IGlzSW50ZXJuYWwgPQogICAgaXNOYXRpdmUgfHwKICAgIChmaWxlbmFtZSAmJgogICAgICAvLyBJdCdzIG5vdCBpbnRlcm5hbCBpZiBpdCdzIGFuIGFic29sdXRlIGxpbnV4IHBhdGgKICAgICAgIWZpbGVuYW1lLnN0YXJ0c1dpdGgoJy8nKSAmJgogICAgICAvLyBJdCdzIG5vdCBpbnRlcm5hbCBpZiBpdCdzIGFuIGFic29sdXRlIHdpbmRvd3MgcGF0aAogICAgICAhZmlsZW5hbWUubWF0Y2goL15bQS1aXTovKSAmJgogICAgICAvLyBJdCdzIG5vdCBpbnRlcm5hbCBpZiB0aGUgcGF0aCBpcyBzdGFydGluZyB3aXRoIGEgZG90CiAgICAgICFmaWxlbmFtZS5zdGFydHNXaXRoKCcuJykgJiYKICAgICAgLy8gSXQncyBub3QgaW50ZXJuYWwgaWYgdGhlIGZyYW1lIGhhcyBhIHByb3RvY29sLiBJbiBub2RlLCB0aGlzIGlzIHVzdWFsbHkgdGhlIGNhc2UgaWYgdGhlIGZpbGUgZ290IHByZS1wcm9jZXNzZWQgd2l0aCBhIGJ1bmRsZXIgbGlrZSB3ZWJwYWNrCiAgICAgICFmaWxlbmFtZS5tYXRjaCgvXlthLXpBLVpdKFthLXpBLVowLTkuXC0rXSkqOlwvXC8vKSk7IC8vIFNjaGVtYSBmcm9tOiBodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL2EvMzY0MTc4MgoKICAvLyBpbl9hcHAgaXMgYWxsIHRoYXQncyBub3QgYW4gaW50ZXJuYWwgTm9kZSBmdW5jdGlvbiBvciBhIG1vZHVsZSB3aXRoaW4gbm9kZV9tb2R1bGVzCiAgLy8gbm90ZSB0aGF0IGlzTmF0aXZlIGFwcGVhcnMgdG8gcmV0dXJuIHRydWUgZXZlbiBmb3Igbm9kZSBjb3JlIGxpYnJhcmllcwogIC8vIHNlZSBodHRwczovL2dpdGh1Yi5jb20vZ2V0c2VudHJ5L3JhdmVuLW5vZGUvaXNzdWVzLzE3NgoKICByZXR1cm4gIWlzSW50ZXJuYWwgJiYgZmlsZW5hbWUgIT09IHVuZGVmaW5lZCAmJiAhZmlsZW5hbWUuaW5jbHVkZXMoJ25vZGVfbW9kdWxlcy8nKTsKfQoKY29uc3QgT05FX1NFQ09ORF9JTl9NUyA9IDEwMDA7CgovKioKICogQSBwYXJ0aWFsIGRlZmluaXRpb24gb2YgdGhlIFtQZXJmb3JtYW5jZSBXZWIgQVBJXXtAbGluayBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvUGVyZm9ybWFuY2V9CiAqIGZvciBhY2Nlc3NpbmcgYSBoaWdoLXJlc29sdXRpb24gbW9ub3RvbmljIGNsb2NrLgogKi8KCi8qKgogKiBSZXR1cm5zIGEgdGltZXN0YW1wIGluIHNlY29uZHMgc2luY2UgdGhlIFVOSVggZXBvY2ggdXNpbmcgdGhlIERhdGUgQVBJLgogKgogKiBUT0RPKHY4KTogUmV0dXJuIHR5cGUgc2hvdWxkIGJlIHJvdW5kZWQuCiAqLwpmdW5jdGlvbiBkYXRlVGltZXN0YW1wSW5TZWNvbmRzKCkgewogIHJldHVybiBEYXRlLm5vdygpIC8gT05FX1NFQ09ORF9JTl9NUzsKfQoKLyoqCiAqIFJldHVybnMgYSB3cmFwcGVyIGFyb3VuZCB0aGUgbmF0aXZlIFBlcmZvcm1hbmNlIEFQSSBicm93c2VyIGltcGxlbWVudGF0aW9uLCBvciB1bmRlZmluZWQgZm9yIGJyb3dzZXJzIHRoYXQgZG8gbm90CiAqIHN1cHBvcnQgdGhlIEFQSS4KICoKICogV3JhcHBpbmcgdGhlIG5hdGl2ZSBBUEkgd29ya3MgYXJvdW5kIGRpZmZlcmVuY2VzIGluIGJlaGF2aW9yIGZyb20gZGlmZmVyZW50IGJyb3dzZXJzLgogKi8KZnVuY3Rpb24gY3JlYXRlVW5peFRpbWVzdGFtcEluU2Vjb25kc0Z1bmMoKSB7CiAgY29uc3QgeyBwZXJmb3JtYW5jZSB9ID0gR0xPQkFMX09CSiA7CiAgaWYgKCFwZXJmb3JtYW5jZSB8fCAhcGVyZm9ybWFuY2Uubm93KSB7CiAgICByZXR1cm4gZGF0ZVRpbWVzdGFtcEluU2Vjb25kczsKICB9CgogIC8vIFNvbWUgYnJvd3NlciBhbmQgZW52aXJvbm1lbnRzIGRvbid0IGhhdmUgYSB0aW1lT3JpZ2luLCBzbyB3ZSBmYWxsYmFjayB0bwogIC8vIHVzaW5nIERhdGUubm93KCkgdG8gY29tcHV0ZSB0aGUgc3RhcnRpbmcgdGltZS4KICBjb25zdCBhcHByb3hTdGFydGluZ1RpbWVPcmlnaW4gPSBEYXRlLm5vdygpIC0gcGVyZm9ybWFuY2Uubm93KCk7CiAgY29uc3QgdGltZU9yaWdpbiA9IHBlcmZvcm1hbmNlLnRpbWVPcmlnaW4gPT0gdW5kZWZpbmVkID8gYXBwcm94U3RhcnRpbmdUaW1lT3JpZ2luIDogcGVyZm9ybWFuY2UudGltZU9yaWdpbjsKCiAgLy8gcGVyZm9ybWFuY2Uubm93KCkgaXMgYSBtb25vdG9uaWMgY2xvY2ssIHdoaWNoIG1lYW5zIGl0IHN0YXJ0cyBhdCAwIHdoZW4gdGhlIHByb2Nlc3MgYmVnaW5zLiBUbyBnZXQgdGhlIGN1cnJlbnQKICAvLyB3YWxsIGNsb2NrIHRpbWUgKGFjdHVhbCBVTklYIHRpbWVzdGFtcCksIHdlIG5lZWQgdG8gYWRkIHRoZSBzdGFydGluZyB0aW1lIG9yaWdpbiBhbmQgdGhlIGN1cnJlbnQgdGltZSBlbGFwc2VkLgogIC8vCiAgLy8gVE9ETzogVGhpcyBkb2VzIG5vdCBhY2NvdW50IGZvciB0aGUgY2FzZSB3aGVyZSB0aGUgbW9ub3RvbmljIGNsb2NrIHRoYXQgcG93ZXJzIHBlcmZvcm1hbmNlLm5vdygpIGRyaWZ0cyBmcm9tIHRoZQogIC8vIHdhbGwgY2xvY2sgdGltZSwgd2hpY2ggY2F1c2VzIHRoZSByZXR1cm5lZCB0aW1lc3RhbXAgdG8gYmUgaW5hY2N1cmF0ZS4gV2Ugc2hvdWxkIGludmVzdGlnYXRlIGhvdyB0byBkZXRlY3QgYW5kCiAgLy8gY29ycmVjdCBmb3IgdGhpcy4KICAvLyBTZWU6IGh0dHBzOi8vZ2l0aHViLmNvbS9nZXRzZW50cnkvc2VudHJ5LWphdmFzY3JpcHQvaXNzdWVzLzI1OTAKICAvLyBTZWU6IGh0dHBzOi8vZ2l0aHViLmNvbS9tZG4vY29udGVudC9pc3N1ZXMvNDcxMwogIC8vIFNlZTogaHR0cHM6Ly9kZXYudG8vbm9hbXIvd2hlbi1hLW1pbGxpc2Vjb25kLWlzLW5vdC1hLW1pbGxpc2Vjb25kLTNoNgogIHJldHVybiAoKSA9PiB7CiAgICByZXR1cm4gKHRpbWVPcmlnaW4gKyBwZXJmb3JtYW5jZS5ub3coKSkgLyBPTkVfU0VDT05EX0lOX01TOwogIH07Cn0KCi8qKgogKiBSZXR1cm5zIGEgdGltZXN0YW1wIGluIHNlY29uZHMgc2luY2UgdGhlIFVOSVggZXBvY2ggdXNpbmcgZWl0aGVyIHRoZSBQZXJmb3JtYW5jZSBvciBEYXRlIEFQSXMsIGRlcGVuZGluZyBvbiB0aGUKICogYXZhaWxhYmlsaXR5IG9mIHRoZSBQZXJmb3JtYW5jZSBBUEkuCiAqCiAqIEJVRzogTm90ZSB0aGF0IGJlY2F1c2Ugb2YgaG93IGJyb3dzZXJzIGltcGxlbWVudCB0aGUgUGVyZm9ybWFuY2UgQVBJLCB0aGUgY2xvY2sgbWlnaHQgc3RvcCB3aGVuIHRoZSBjb21wdXRlciBpcwogKiBhc2xlZXAuIFRoaXMgY3JlYXRlcyBhIHNrZXcgYmV0d2VlbiBgZGF0ZVRpbWVzdGFtcEluU2Vjb25kc2AgYW5kIGB0aW1lc3RhbXBJblNlY29uZHNgLiBUaGUKICogc2tldyBjYW4gZ3JvdyB0byBhcmJpdHJhcnkgYW1vdW50cyBsaWtlIGRheXMsIHdlZWtzIG9yIG1vbnRocy4KICogU2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9nZXRzZW50cnkvc2VudHJ5LWphdmFzY3JpcHQvaXNzdWVzLzI1OTAuCiAqLwpjb25zdCB0aW1lc3RhbXBJblNlY29uZHMgPSBjcmVhdGVVbml4VGltZXN0YW1wSW5TZWNvbmRzRnVuYygpOwoKLyoqCiAqIFRoZSBudW1iZXIgb2YgbWlsbGlzZWNvbmRzIHNpbmNlIHRoZSBVTklYIGVwb2NoLiBUaGlzIHZhbHVlIGlzIG9ubHkgdXNhYmxlIGluIGEgYnJvd3NlciwgYW5kIG9ubHkgd2hlbiB0aGUKICogcGVyZm9ybWFuY2UgQVBJIGlzIGF2YWlsYWJsZS4KICovCigoKSA9PiB7CiAgLy8gVW5mb3J0dW5hdGVseSBicm93c2VycyBtYXkgcmVwb3J0IGFuIGluYWNjdXJhdGUgdGltZSBvcmlnaW4gZGF0YSwgdGhyb3VnaCBlaXRoZXIgcGVyZm9ybWFuY2UudGltZU9yaWdpbiBvcgogIC8vIHBlcmZvcm1hbmNlLnRpbWluZy5uYXZpZ2F0aW9uU3RhcnQsIHdoaWNoIHJlc3VsdHMgaW4gcG9vciByZXN1bHRzIGluIHBlcmZvcm1hbmNlIGRhdGEuIFdlIG9ubHkgdHJlYXQgdGltZSBvcmlnaW4KICAvLyBkYXRhIGFzIHJlbGlhYmxlIGlmIHRoZXkgYXJlIHdpdGhpbiBhIHJlYXNvbmFibGUgdGhyZXNob2xkIG9mIHRoZSBjdXJyZW50IHRpbWUuCgogIGNvbnN0IHsgcGVyZm9ybWFuY2UgfSA9IEdMT0JBTF9PQkogOwogIGlmICghcGVyZm9ybWFuY2UgfHwgIXBlcmZvcm1hbmNlLm5vdykgewogICAgcmV0dXJuIHVuZGVmaW5lZDsKICB9CgogIGNvbnN0IHRocmVzaG9sZCA9IDM2MDAgKiAxMDAwOwogIGNvbnN0IHBlcmZvcm1hbmNlTm93ID0gcGVyZm9ybWFuY2Uubm93KCk7CiAgY29uc3QgZGF0ZU5vdyA9IERhdGUubm93KCk7CgogIC8vIGlmIHRpbWVPcmlnaW4gaXNuJ3QgYXZhaWxhYmxlIHNldCBkZWx0YSB0byB0aHJlc2hvbGQgc28gaXQgaXNuJ3QgdXNlZAogIGNvbnN0IHRpbWVPcmlnaW5EZWx0YSA9IHBlcmZvcm1hbmNlLnRpbWVPcmlnaW4KICAgID8gTWF0aC5hYnMocGVyZm9ybWFuY2UudGltZU9yaWdpbiArIHBlcmZvcm1hbmNlTm93IC0gZGF0ZU5vdykKICAgIDogdGhyZXNob2xkOwogIGNvbnN0IHRpbWVPcmlnaW5Jc1JlbGlhYmxlID0gdGltZU9yaWdpbkRlbHRhIDwgdGhyZXNob2xkOwoKICAvLyBXaGlsZSBwZXJmb3JtYW5jZS50aW1pbmcubmF2aWdhdGlvblN0YXJ0IGlzIGRlcHJlY2F0ZWQgaW4gZmF2b3Igb2YgcGVyZm9ybWFuY2UudGltZU9yaWdpbiwgcGVyZm9ybWFuY2UudGltZU9yaWdpbgogIC8vIGlzIG5vdCBhcyB3aWRlbHkgc3VwcG9ydGVkLiBOYW1lbHksIHBlcmZvcm1hbmNlLnRpbWVPcmlnaW4gaXMgdW5kZWZpbmVkIGluIFNhZmFyaSBhcyBvZiB3cml0aW5nLgogIC8vIEFsc28gYXMgb2Ygd3JpdGluZywgcGVyZm9ybWFuY2UudGltaW5nIGlzIG5vdCBhdmFpbGFibGUgaW4gV2ViIFdvcmtlcnMgaW4gbWFpbnN0cmVhbSBicm93c2Vycywgc28gaXQgaXMgbm90IGFsd2F5cwogIC8vIGEgdmFsaWQgZmFsbGJhY2suIEluIHRoZSBhYnNlbmNlIG9mIGFuIGluaXRpYWwgdGltZSBwcm92aWRlZCBieSB0aGUgYnJvd3NlciwgZmFsbGJhY2sgdG8gdGhlIGN1cnJlbnQgdGltZSBmcm9tIHRoZQogIC8vIERhdGUgQVBJLgogIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBkZXByZWNhdGlvbi9kZXByZWNhdGlvbgogIGNvbnN0IG5hdmlnYXRpb25TdGFydCA9IHBlcmZvcm1hbmNlLnRpbWluZyAmJiBwZXJmb3JtYW5jZS50aW1pbmcubmF2aWdhdGlvblN0YXJ0OwogIGNvbnN0IGhhc05hdmlnYXRpb25TdGFydCA9IHR5cGVvZiBuYXZpZ2F0aW9uU3RhcnQgPT09ICdudW1iZXInOwogIC8vIGlmIG5hdmlnYXRpb25TdGFydCBpc24ndCBhdmFpbGFibGUgc2V0IGRlbHRhIHRvIHRocmVzaG9sZCBzbyBpdCBpc24ndCB1c2VkCiAgY29uc3QgbmF2aWdhdGlvblN0YXJ0RGVsdGEgPSBoYXNOYXZpZ2F0aW9uU3RhcnQgPyBNYXRoLmFicyhuYXZpZ2F0aW9uU3RhcnQgKyBwZXJmb3JtYW5jZU5vdyAtIGRhdGVOb3cpIDogdGhyZXNob2xkOwogIGNvbnN0IG5hdmlnYXRpb25TdGFydElzUmVsaWFibGUgPSBuYXZpZ2F0aW9uU3RhcnREZWx0YSA8IHRocmVzaG9sZDsKCiAgaWYgKHRpbWVPcmlnaW5Jc1JlbGlhYmxlIHx8IG5hdmlnYXRpb25TdGFydElzUmVsaWFibGUpIHsKICAgIC8vIFVzZSB0aGUgbW9yZSByZWxpYWJsZSB0aW1lIG9yaWdpbgogICAgaWYgKHRpbWVPcmlnaW5EZWx0YSA8PSBuYXZpZ2F0aW9uU3RhcnREZWx0YSkgewogICAgICByZXR1cm4gcGVyZm9ybWFuY2UudGltZU9yaWdpbjsKICAgIH0gZWxzZSB7CiAgICAgIHJldHVybiBuYXZpZ2F0aW9uU3RhcnQ7CiAgICB9CiAgfQogIHJldHVybiBkYXRlTm93Owp9KSgpOwoKLyoqCiAqIENyZWF0ZXMgYW4gZW52ZWxvcGUuCiAqIE1ha2Ugc3VyZSB0byBhbHdheXMgZXhwbGljaXRseSBwcm92aWRlIHRoZSBnZW5lcmljIHRvIHRoaXMgZnVuY3Rpb24KICogc28gdGhhdCB0aGUgZW52ZWxvcGUgdHlwZXMgcmVzb2x2ZSBjb3JyZWN0bHkuCiAqLwpmdW5jdGlvbiBjcmVhdGVFbnZlbG9wZShoZWFkZXJzLCBpdGVtcyA9IFtdKSB7CiAgcmV0dXJuIFtoZWFkZXJzLCBpdGVtc10gOwp9CgovKioKICogQ29udmVuaWVuY2UgZnVuY3Rpb24gdG8gbG9vcCB0aHJvdWdoIHRoZSBpdGVtcyBhbmQgaXRlbSB0eXBlcyBvZiBhbiBlbnZlbG9wZS4KICogKFRoaXMgZnVuY3Rpb24gd2FzIG1vc3RseSBjcmVhdGVkIGJlY2F1c2Ugd29ya2luZyB3aXRoIGVudmVsb3BlIHR5cGVzIGlzIHBhaW5mdWwgYXQgdGhlIG1vbWVudCkKICoKICogSWYgdGhlIGNhbGxiYWNrIHJldHVybnMgdHJ1ZSwgdGhlIHJlc3Qgb2YgdGhlIGl0ZW1zIHdpbGwgYmUgc2tpcHBlZC4KICovCmZ1bmN0aW9uIGZvckVhY2hFbnZlbG9wZUl0ZW0oCiAgZW52ZWxvcGUsCiAgY2FsbGJhY2ssCikgewogIGNvbnN0IGVudmVsb3BlSXRlbXMgPSBlbnZlbG9wZVsxXTsKCiAgZm9yIChjb25zdCBlbnZlbG9wZUl0ZW0gb2YgZW52ZWxvcGVJdGVtcykgewogICAgY29uc3QgZW52ZWxvcGVJdGVtVHlwZSA9IGVudmVsb3BlSXRlbVswXS50eXBlOwogICAgY29uc3QgcmVzdWx0ID0gY2FsbGJhY2soZW52ZWxvcGVJdGVtLCBlbnZlbG9wZUl0ZW1UeXBlKTsKCiAgICBpZiAocmVzdWx0KSB7CiAgICAgIHJldHVybiB0cnVlOwogICAgfQogIH0KCiAgcmV0dXJuIGZhbHNlOwp9CgovKioKICogRW5jb2RlIGEgc3RyaW5nIHRvIFVURjggYXJyYXkuCiAqLwpmdW5jdGlvbiBlbmNvZGVVVEY4KGlucHV0KSB7CiAgcmV0dXJuIEdMT0JBTF9PQkouX19TRU5UUllfXyAmJiBHTE9CQUxfT0JKLl9fU0VOVFJZX18uZW5jb2RlUG9seWZpbGwKICAgID8gR0xPQkFMX09CSi5fX1NFTlRSWV9fLmVuY29kZVBvbHlmaWxsKGlucHV0KQogICAgOiBuZXcgVGV4dEVuY29kZXIoKS5lbmNvZGUoaW5wdXQpOwp9CgovKioKICogU2VyaWFsaXplcyBhbiBlbnZlbG9wZS4KICovCmZ1bmN0aW9uIHNlcmlhbGl6ZUVudmVsb3BlKGVudmVsb3BlKSB7CiAgY29uc3QgW2VudkhlYWRlcnMsIGl0ZW1zXSA9IGVudmVsb3BlOwoKICAvLyBJbml0aWFsbHkgd2UgY29uc3RydWN0IG91ciBlbnZlbG9wZSBhcyBhIHN0cmluZyBhbmQgb25seSBjb252ZXJ0IHRvIGJpbmFyeSBjaHVua3MgaWYgd2UgZW5jb3VudGVyIGJpbmFyeSBkYXRhCiAgbGV0IHBhcnRzID0gSlNPTi5zdHJpbmdpZnkoZW52SGVhZGVycyk7CgogIGZ1bmN0aW9uIGFwcGVuZChuZXh0KSB7CiAgICBpZiAodHlwZW9mIHBhcnRzID09PSAnc3RyaW5nJykgewogICAgICBwYXJ0cyA9IHR5cGVvZiBuZXh0ID09PSAnc3RyaW5nJyA/IHBhcnRzICsgbmV4dCA6IFtlbmNvZGVVVEY4KHBhcnRzKSwgbmV4dF07CiAgICB9IGVsc2UgewogICAgICBwYXJ0cy5wdXNoKHR5cGVvZiBuZXh0ID09PSAnc3RyaW5nJyA/IGVuY29kZVVURjgobmV4dCkgOiBuZXh0KTsKICAgIH0KICB9CgogIGZvciAoY29uc3QgaXRlbSBvZiBpdGVtcykgewogICAgY29uc3QgW2l0ZW1IZWFkZXJzLCBwYXlsb2FkXSA9IGl0ZW07CgogICAgYXBwZW5kKGBcbiR7SlNPTi5zdHJpbmdpZnkoaXRlbUhlYWRlcnMpfVxuYCk7CgogICAgaWYgKHR5cGVvZiBwYXlsb2FkID09PSAnc3RyaW5nJyB8fCBwYXlsb2FkIGluc3RhbmNlb2YgVWludDhBcnJheSkgewogICAgICBhcHBlbmQocGF5bG9hZCk7CiAgICB9IGVsc2UgewogICAgICBsZXQgc3RyaW5naWZpZWRQYXlsb2FkOwogICAgICB0cnkgewogICAgICAgIHN0cmluZ2lmaWVkUGF5bG9hZCA9IEpTT04uc3RyaW5naWZ5KHBheWxvYWQpOwogICAgICB9IGNhdGNoIChlKSB7CiAgICAgICAgLy8gSW4gY2FzZSwgZGVzcGl0ZSBhbGwgb3VyIGVmZm9ydHMgdG8ga2VlcCBgcGF5bG9hZGAgY2lyY3VsYXItZGVwZW5kZW5jeS1mcmVlLCBgSlNPTi5zdHJpbmlmeSgpYCBzdGlsbAogICAgICAgIC8vIGZhaWxzLCB3ZSB0cnkgYWdhaW4gYWZ0ZXIgbm9ybWFsaXppbmcgaXQgYWdhaW4gd2l0aCBpbmZpbml0ZSBub3JtYWxpemF0aW9uIGRlcHRoLiBUaGlzIG9mIGNvdXJzZSBoYXMgYQogICAgICAgIC8vIHBlcmZvcm1hbmNlIGltcGFjdCBidXQgaW4gdGhpcyBjYXNlIGEgcGVyZm9ybWFuY2UgaGl0IGlzIGJldHRlciB0aGFuIHRocm93aW5nLgogICAgICAgIHN0cmluZ2lmaWVkUGF5bG9hZCA9IEpTT04uc3RyaW5naWZ5KG5vcm1hbGl6ZShwYXlsb2FkKSk7CiAgICAgIH0KICAgICAgYXBwZW5kKHN0cmluZ2lmaWVkUGF5bG9hZCk7CiAgICB9CiAgfQoKICByZXR1cm4gdHlwZW9mIHBhcnRzID09PSAnc3RyaW5nJyA/IHBhcnRzIDogY29uY2F0QnVmZmVycyhwYXJ0cyk7Cn0KCmZ1bmN0aW9uIGNvbmNhdEJ1ZmZlcnMoYnVmZmVycykgewogIGNvbnN0IHRvdGFsTGVuZ3RoID0gYnVmZmVycy5yZWR1Y2UoKGFjYywgYnVmKSA9PiBhY2MgKyBidWYubGVuZ3RoLCAwKTsKCiAgY29uc3QgbWVyZ2VkID0gbmV3IFVpbnQ4QXJyYXkodG90YWxMZW5ndGgpOwogIGxldCBvZmZzZXQgPSAwOwogIGZvciAoY29uc3QgYnVmZmVyIG9mIGJ1ZmZlcnMpIHsKICAgIG1lcmdlZC5zZXQoYnVmZmVyLCBvZmZzZXQpOwogICAgb2Zmc2V0ICs9IGJ1ZmZlci5sZW5ndGg7CiAgfQoKICByZXR1cm4gbWVyZ2VkOwp9Cgpjb25zdCBJVEVNX1RZUEVfVE9fREFUQV9DQVRFR09SWV9NQVAgPSB7CiAgc2Vzc2lvbjogJ3Nlc3Npb24nLAogIHNlc3Npb25zOiAnc2Vzc2lvbicsCiAgYXR0YWNobWVudDogJ2F0dGFjaG1lbnQnLAogIHRyYW5zYWN0aW9uOiAndHJhbnNhY3Rpb24nLAogIGV2ZW50OiAnZXJyb3InLAogIGNsaWVudF9yZXBvcnQ6ICdpbnRlcm5hbCcsCiAgdXNlcl9yZXBvcnQ6ICdkZWZhdWx0JywKICBwcm9maWxlOiAncHJvZmlsZScsCiAgcmVwbGF5X2V2ZW50OiAncmVwbGF5JywKICByZXBsYXlfcmVjb3JkaW5nOiAncmVwbGF5JywKICBjaGVja19pbjogJ21vbml0b3InLAogIGZlZWRiYWNrOiAnZmVlZGJhY2snLAogIHNwYW46ICdzcGFuJywKICBzdGF0c2Q6ICdtZXRyaWNfYnVja2V0JywKfTsKCi8qKgogKiBNYXBzIHRoZSB0eXBlIG9mIGFuIGVudmVsb3BlIGl0ZW0gdG8gYSBkYXRhIGNhdGVnb3J5LgogKi8KZnVuY3Rpb24gZW52ZWxvcGVJdGVtVHlwZVRvRGF0YUNhdGVnb3J5KHR5cGUpIHsKICByZXR1cm4gSVRFTV9UWVBFX1RPX0RBVEFfQ0FURUdPUllfTUFQW3R5cGVdOwp9CgovKiogRXh0cmFjdHMgdGhlIG1pbmltYWwgU0RLIGluZm8gZnJvbSB0aGUgbWV0YWRhdGEgb3IgYW4gZXZlbnRzICovCmZ1bmN0aW9uIGdldFNka01ldGFkYXRhRm9yRW52ZWxvcGVIZWFkZXIobWV0YWRhdGFPckV2ZW50KSB7CiAgaWYgKCFtZXRhZGF0YU9yRXZlbnQgfHwgIW1ldGFkYXRhT3JFdmVudC5zZGspIHsKICAgIHJldHVybjsKICB9CiAgY29uc3QgeyBuYW1lLCB2ZXJzaW9uIH0gPSBtZXRhZGF0YU9yRXZlbnQuc2RrOwogIHJldHVybiB7IG5hbWUsIHZlcnNpb24gfTsKfQoKLyoqCiAqIENyZWF0ZXMgZXZlbnQgZW52ZWxvcGUgaGVhZGVycywgYmFzZWQgb24gZXZlbnQsIHNkayBpbmZvIGFuZCB0dW5uZWwKICogTm90ZTogVGhpcyBmdW5jdGlvbiB3YXMgZXh0cmFjdGVkIGZyb20gdGhlIGNvcmUgcGFja2FnZSB0byBtYWtlIGl0IGF2YWlsYWJsZSBpbiBSZXBsYXkKICovCmZ1bmN0aW9uIGNyZWF0ZUV2ZW50RW52ZWxvcGVIZWFkZXJzKAogIGV2ZW50LAogIHNka0luZm8sCiAgdHVubmVsLAogIGRzbiwKKSB7CiAgY29uc3QgZHluYW1pY1NhbXBsaW5nQ29udGV4dCA9IGV2ZW50LnNka1Byb2Nlc3NpbmdNZXRhZGF0YSAmJiBldmVudC5zZGtQcm9jZXNzaW5nTWV0YWRhdGEuZHluYW1pY1NhbXBsaW5nQ29udGV4dDsKICByZXR1cm4gewogICAgZXZlbnRfaWQ6IGV2ZW50LmV2ZW50X2lkICwKICAgIHNlbnRfYXQ6IG5ldyBEYXRlKCkudG9JU09TdHJpbmcoKSwKICAgIC4uLihzZGtJbmZvICYmIHsgc2RrOiBzZGtJbmZvIH0pLAogICAgLi4uKCEhdHVubmVsICYmIGRzbiAmJiB7IGRzbjogZHNuVG9TdHJpbmcoZHNuKSB9KSwKICAgIC4uLihkeW5hbWljU2FtcGxpbmdDb250ZXh0ICYmIHsKICAgICAgdHJhY2U6IGRyb3BVbmRlZmluZWRLZXlzKHsgLi4uZHluYW1pY1NhbXBsaW5nQ29udGV4dCB9KSwKICAgIH0pLAogIH07Cn0KCi8vIEludGVudGlvbmFsbHkga2VlcGluZyB0aGUga2V5IGJyb2FkLCBhcyB3ZSBkb24ndCBrbm93IGZvciBzdXJlIHdoYXQgcmF0ZSBsaW1pdCBoZWFkZXJzIGdldCByZXR1cm5lZCBmcm9tIGJhY2tlbmQKCmNvbnN0IERFRkFVTFRfUkVUUllfQUZURVIgPSA2MCAqIDEwMDA7IC8vIDYwIHNlY29uZHMKCi8qKgogKiBFeHRyYWN0cyBSZXRyeS1BZnRlciB2YWx1ZSBmcm9tIHRoZSByZXF1ZXN0IGhlYWRlciBvciByZXR1cm5zIGRlZmF1bHQgdmFsdWUKICogQHBhcmFtIGhlYWRlciBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgJ1JldHJ5LUFmdGVyJyBoZWFkZXIKICogQHBhcmFtIG5vdyBjdXJyZW50IHVuaXggdGltZXN0YW1wCiAqCiAqLwpmdW5jdGlvbiBwYXJzZVJldHJ5QWZ0ZXJIZWFkZXIoaGVhZGVyLCBub3cgPSBEYXRlLm5vdygpKSB7CiAgY29uc3QgaGVhZGVyRGVsYXkgPSBwYXJzZUludChgJHtoZWFkZXJ9YCwgMTApOwogIGlmICghaXNOYU4oaGVhZGVyRGVsYXkpKSB7CiAgICByZXR1cm4gaGVhZGVyRGVsYXkgKiAxMDAwOwogIH0KCiAgY29uc3QgaGVhZGVyRGF0ZSA9IERhdGUucGFyc2UoYCR7aGVhZGVyfWApOwogIGlmICghaXNOYU4oaGVhZGVyRGF0ZSkpIHsKICAgIHJldHVybiBoZWFkZXJEYXRlIC0gbm93OwogIH0KCiAgcmV0dXJuIERFRkFVTFRfUkVUUllfQUZURVI7Cn0KCi8qKgogKiBHZXRzIHRoZSB0aW1lIHRoYXQgdGhlIGdpdmVuIGNhdGVnb3J5IGlzIGRpc2FibGVkIHVudGlsIGZvciByYXRlIGxpbWl0aW5nLgogKiBJbiBjYXNlIG5vIGNhdGVnb3J5LXNwZWNpZmljIGxpbWl0IGlzIHNldCBidXQgYSBnZW5lcmFsIHJhdGUgbGltaXQgYWNyb3NzIGFsbCBjYXRlZ29yaWVzIGlzIGFjdGl2ZSwKICogdGhhdCB0aW1lIGlzIHJldHVybmVkLgogKgogKiBAcmV0dXJuIHRoZSB0aW1lIGluIG1zIHRoYXQgdGhlIGNhdGVnb3J5IGlzIGRpc2FibGVkIHVudGlsIG9yIDAgaWYgdGhlcmUncyBubyBhY3RpdmUgcmF0ZSBsaW1pdC4KICovCmZ1bmN0aW9uIGRpc2FibGVkVW50aWwobGltaXRzLCBkYXRhQ2F0ZWdvcnkpIHsKICByZXR1cm4gbGltaXRzW2RhdGFDYXRlZ29yeV0gfHwgbGltaXRzLmFsbCB8fCAwOwp9CgovKioKICogQ2hlY2tzIGlmIGEgY2F0ZWdvcnkgaXMgcmF0ZSBsaW1pdGVkCiAqLwpmdW5jdGlvbiBpc1JhdGVMaW1pdGVkKGxpbWl0cywgZGF0YUNhdGVnb3J5LCBub3cgPSBEYXRlLm5vdygpKSB7CiAgcmV0dXJuIGRpc2FibGVkVW50aWwobGltaXRzLCBkYXRhQ2F0ZWdvcnkpID4gbm93Owp9CgovKioKICogVXBkYXRlIHJhdGVsaW1pdHMgZnJvbSBpbmNvbWluZyBoZWFkZXJzLgogKgogKiBAcmV0dXJuIHRoZSB1cGRhdGVkIFJhdGVMaW1pdHMgb2JqZWN0LgogKi8KZnVuY3Rpb24gdXBkYXRlUmF0ZUxpbWl0cygKICBsaW1pdHMsCiAgeyBzdGF0dXNDb2RlLCBoZWFkZXJzIH0sCiAgbm93ID0gRGF0ZS5ub3coKSwKKSB7CiAgY29uc3QgdXBkYXRlZFJhdGVMaW1pdHMgPSB7CiAgICAuLi5saW1pdHMsCiAgfTsKCiAgLy8gIlRoZSBuYW1lIGlzIGNhc2UtaW5zZW5zaXRpdmUuIgogIC8vIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9IZWFkZXJzL2dldAogIGNvbnN0IHJhdGVMaW1pdEhlYWRlciA9IGhlYWRlcnMgJiYgaGVhZGVyc1sneC1zZW50cnktcmF0ZS1saW1pdHMnXTsKICBjb25zdCByZXRyeUFmdGVySGVhZGVyID0gaGVhZGVycyAmJiBoZWFkZXJzWydyZXRyeS1hZnRlciddOwoKICBpZiAocmF0ZUxpbWl0SGVhZGVyKSB7CiAgICAvKioKICAgICAqIHJhdGUgbGltaXQgaGVhZGVycyBhcmUgb2YgdGhlIGZvcm0KICAgICAqICAgICA8aGVhZGVyPiw8aGVhZGVyPiwuLgogICAgICogd2hlcmUgZWFjaCA8aGVhZGVyPiBpcyBvZiB0aGUgZm9ybQogICAgICogICAgIDxyZXRyeV9hZnRlcj46IDxjYXRlZ29yaWVzPjogPHNjb3BlPjogPHJlYXNvbl9jb2RlPjogPG5hbWVzcGFjZXM+CiAgICAgKiB3aGVyZQogICAgICogICAgIDxyZXRyeV9hZnRlcj4gaXMgYSBkZWxheSBpbiBzZWNvbmRzCiAgICAgKiAgICAgPGNhdGVnb3JpZXM+IGlzIHRoZSBldmVudCB0eXBlKHMpIChlcnJvciwgdHJhbnNhY3Rpb24sIGV0YykgYmVpbmcgcmF0ZSBsaW1pdGVkIGFuZCBpcyBvZiB0aGUgZm9ybQogICAgICogICAgICAgICA8Y2F0ZWdvcnk+OzxjYXRlZ29yeT47Li4uCiAgICAgKiAgICAgPHNjb3BlPiBpcyB3aGF0J3MgYmVpbmcgbGltaXRlZCAob3JnLCBwcm9qZWN0LCBvciBrZXkpIC0gaWdub3JlZCBieSBTREsKICAgICAqICAgICA8cmVhc29uX2NvZGU+IGlzIGFuIGFyYml0cmFyeSBzdHJpbmcgbGlrZSAib3JnX3F1b3RhIiAtIGlnbm9yZWQgYnkgU0RLCiAgICAgKiAgICAgPG5hbWVzcGFjZXM+IFNlbWljb2xvbi1zZXBhcmF0ZWQgbGlzdCBvZiBtZXRyaWMgbmFtZXNwYWNlIGlkZW50aWZpZXJzLiBEZWZpbmVzIHdoaWNoIG5hbWVzcGFjZShzKSB3aWxsIGJlIGFmZmVjdGVkLgogICAgICogICAgICAgICBPbmx5IHByZXNlbnQgaWYgcmF0ZSBsaW1pdCBhcHBsaWVzIHRvIHRoZSBtZXRyaWNfYnVja2V0IGRhdGEgY2F0ZWdvcnkuCiAgICAgKi8KICAgIGZvciAoY29uc3QgbGltaXQgb2YgcmF0ZUxpbWl0SGVhZGVyLnRyaW0oKS5zcGxpdCgnLCcpKSB7CiAgICAgIGNvbnN0IFtyZXRyeUFmdGVyLCBjYXRlZ29yaWVzLCAsICwgbmFtZXNwYWNlc10gPSBsaW1pdC5zcGxpdCgnOicsIDUpOwogICAgICBjb25zdCBoZWFkZXJEZWxheSA9IHBhcnNlSW50KHJldHJ5QWZ0ZXIsIDEwKTsKICAgICAgY29uc3QgZGVsYXkgPSAoIWlzTmFOKGhlYWRlckRlbGF5KSA/IGhlYWRlckRlbGF5IDogNjApICogMTAwMDsgLy8gNjBzZWMgZGVmYXVsdAogICAgICBpZiAoIWNhdGVnb3JpZXMpIHsKICAgICAgICB1cGRhdGVkUmF0ZUxpbWl0cy5hbGwgPSBub3cgKyBkZWxheTsKICAgICAgfSBlbHNlIHsKICAgICAgICBmb3IgKGNvbnN0IGNhdGVnb3J5IG9mIGNhdGVnb3JpZXMuc3BsaXQoJzsnKSkgewogICAgICAgICAgaWYgKGNhdGVnb3J5ID09PSAnbWV0cmljX2J1Y2tldCcpIHsKICAgICAgICAgICAgLy8gbmFtZXNwYWNlcyB3aWxsIGJlIHByZXNlbnQgd2hlbiBjYXRlZ29yeSA9PT0gJ21ldHJpY19idWNrZXQnCiAgICAgICAgICAgIGlmICghbmFtZXNwYWNlcyB8fCBuYW1lc3BhY2VzLnNwbGl0KCc7JykuaW5jbHVkZXMoJ2N1c3RvbScpKSB7CiAgICAgICAgICAgICAgdXBkYXRlZFJhdGVMaW1pdHNbY2F0ZWdvcnldID0gbm93ICsgZGVsYXk7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIHVwZGF0ZWRSYXRlTGltaXRzW2NhdGVnb3J5XSA9IG5vdyArIGRlbGF5OwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgfQogICAgfQogIH0gZWxzZSBpZiAocmV0cnlBZnRlckhlYWRlcikgewogICAgdXBkYXRlZFJhdGVMaW1pdHMuYWxsID0gbm93ICsgcGFyc2VSZXRyeUFmdGVySGVhZGVyKHJldHJ5QWZ0ZXJIZWFkZXIsIG5vdyk7CiAgfSBlbHNlIGlmIChzdGF0dXNDb2RlID09PSA0MjkpIHsKICAgIHVwZGF0ZWRSYXRlTGltaXRzLmFsbCA9IG5vdyArIDYwICogMTAwMDsKICB9CgogIHJldHVybiB1cGRhdGVkUmF0ZUxpbWl0czsKfQoKLyoqCiAqIEEgbm9kZS5qcyB3YXRjaGRvZyB0aW1lcgogKiBAcGFyYW0gcG9sbEludGVydmFsIFRoZSBpbnRlcnZhbCB0aGF0IHdlIGV4cGVjdCB0byBnZXQgcG9sbGVkIGF0CiAqIEBwYXJhbSBhbnJUaHJlc2hvbGQgVGhlIHRocmVzaG9sZCBmb3Igd2hlbiB3ZSBjb25zaWRlciBBTlIKICogQHBhcmFtIGNhbGxiYWNrIFRoZSBjYWxsYmFjayB0byBjYWxsIGZvciBBTlIKICogQHJldHVybnMgQW4gb2JqZWN0IHdpdGggYHBvbGxgIGFuZCBgZW5hYmxlZGAgZnVuY3Rpb25zIHtAbGluayBXYXRjaGRvZ1JldHVybn0KICovCmZ1bmN0aW9uIHdhdGNoZG9nVGltZXIoCiAgY3JlYXRlVGltZXIsCiAgcG9sbEludGVydmFsLAogIGFuclRocmVzaG9sZCwKICBjYWxsYmFjaywKKSB7CiAgY29uc3QgdGltZXIgPSBjcmVhdGVUaW1lcigpOwogIGxldCB0cmlnZ2VyZWQgPSBmYWxzZTsKICBsZXQgZW5hYmxlZCA9IHRydWU7CgogIHNldEludGVydmFsKCgpID0+IHsKICAgIGNvbnN0IGRpZmZNcyA9IHRpbWVyLmdldFRpbWVNcygpOwoKICAgIGlmICh0cmlnZ2VyZWQgPT09IGZhbHNlICYmIGRpZmZNcyA+IHBvbGxJbnRlcnZhbCArIGFuclRocmVzaG9sZCkgewogICAgICB0cmlnZ2VyZWQgPSB0cnVlOwogICAgICBpZiAoZW5hYmxlZCkgewogICAgICAgIGNhbGxiYWNrKCk7CiAgICAgIH0KICAgIH0KCiAgICBpZiAoZGlmZk1zIDwgcG9sbEludGVydmFsICsgYW5yVGhyZXNob2xkKSB7CiAgICAgIHRyaWdnZXJlZCA9IGZhbHNlOwogICAgfQogIH0sIDIwKTsKCiAgcmV0dXJuIHsKICAgIHBvbGw6ICgpID0+IHsKICAgICAgdGltZXIucmVzZXQoKTsKICAgIH0sCiAgICBlbmFibGVkOiAoc3RhdGUpID0+IHsKICAgICAgZW5hYmxlZCA9IHN0YXRlOwogICAgfSwKICB9Owp9CgovLyB0eXBlcyBjb3BpZWQgZnJvbSBpbnNwZWN0b3IuZC50cwoKLyoqCiAqIENvbnZlcnRzIERlYnVnZ2VyLkNhbGxGcmFtZSB0byBTZW50cnkgU3RhY2tGcmFtZQogKi8KZnVuY3Rpb24gY2FsbEZyYW1lVG9TdGFja0ZyYW1lKAogIGZyYW1lLAogIHVybCwKICBnZXRNb2R1bGVGcm9tRmlsZW5hbWUsCikgewogIGNvbnN0IGZpbGVuYW1lID0gdXJsID8gdXJsLnJlcGxhY2UoL15maWxlOlwvXC8vLCAnJykgOiB1bmRlZmluZWQ7CgogIC8vIENhbGxGcmFtZSByb3cvY29sIGFyZSAwIGJhc2VkLCB3aGVyZWFzIFN0YWNrRnJhbWUgYXJlIDEgYmFzZWQKICBjb25zdCBjb2xubyA9IGZyYW1lLmxvY2F0aW9uLmNvbHVtbk51bWJlciA/IGZyYW1lLmxvY2F0aW9uLmNvbHVtbk51bWJlciArIDEgOiB1bmRlZmluZWQ7CiAgY29uc3QgbGluZW5vID0gZnJhbWUubG9jYXRpb24ubGluZU51bWJlciA/IGZyYW1lLmxvY2F0aW9uLmxpbmVOdW1iZXIgKyAxIDogdW5kZWZpbmVkOwoKICByZXR1cm4gZHJvcFVuZGVmaW5lZEtleXMoewogICAgZmlsZW5hbWUsCiAgICBtb2R1bGU6IGdldE1vZHVsZUZyb21GaWxlbmFtZShmaWxlbmFtZSksCiAgICBmdW5jdGlvbjogZnJhbWUuZnVuY3Rpb25OYW1lIHx8IFVOS05PV05fRlVOQ1RJT04sCiAgICBjb2xubywKICAgIGxpbmVubywKICAgIGluX2FwcDogZmlsZW5hbWUgPyBmaWxlbmFtZUlzSW5BcHAoZmlsZW5hbWUpIDogdW5kZWZpbmVkLAogIH0pOwp9CgovKioKICogVGhpcyBzZXJ2ZXMgYXMgYSBidWlsZCB0aW1lIGZsYWcgdGhhdCB3aWxsIGJlIHRydWUgYnkgZGVmYXVsdCwgYnV0IGZhbHNlIGluIG5vbi1kZWJ1ZyBidWlsZHMgb3IgaWYgdXNlcnMgcmVwbGFjZSBgX19TRU5UUllfREVCVUdfX2AgaW4gdGhlaXIgZ2VuZXJhdGVkIGNvZGUuCiAqCiAqIEFUVEVOVElPTjogVGhpcyBjb25zdGFudCBtdXN0IG5ldmVyIGNyb3NzIHBhY2thZ2UgYm91bmRhcmllcyAoaS5lLiBiZSBleHBvcnRlZCkgdG8gZ3VhcmFudGVlIHRoYXQgaXQgY2FuIGJlIHVzZWQgZm9yIHRyZWUgc2hha2luZy4KICovCmNvbnN0IERFQlVHX0JVSUxEID0gKHR5cGVvZiBfX1NFTlRSWV9ERUJVR19fID09PSAndW5kZWZpbmVkJyB8fCBfX1NFTlRSWV9ERUJVR19fKTsKCi8qKgogKiBAcHJpdmF0ZSBQcml2YXRlIEFQSSB3aXRoIG5vIHNlbXZlciBndWFyYW50ZWVzIQogKgogKiBTdHJhdGVneSB1c2VkIHRvIHRyYWNrIGFzeW5jIGNvbnRleHQuCiAqLwoKLyoqCiAqIFJldHVybnMgdGhlIGdsb2JhbCBzaGltIHJlZ2lzdHJ5LgogKgogKiBGSVhNRTogVGhpcyBmdW5jdGlvbiBpcyBwcm9ibGVtYXRpYywgYmVjYXVzZSBkZXNwaXRlIGFsd2F5cyByZXR1cm5pbmcgYSB2YWxpZCBDYXJyaWVyLAogKiBpdCBoYXMgYW4gb3B0aW9uYWwgYF9fU0VOVFJZX19gIHByb3BlcnR5LCB3aGljaCB0aGVuIGluIHR1cm4gcmVxdWlyZXMgdXMgdG8gYWx3YXlzIHBlcmZvcm0gYW4gdW5uZWNlc3NhcnkgY2hlY2sKICogYXQgdGhlIGNhbGwtc2l0ZS4gV2UgYWx3YXlzIGFjY2VzcyB0aGUgY2FycmllciB0aHJvdWdoIHRoaXMgZnVuY3Rpb24sIHNvIHdlIGNhbiBndWFyYW50ZWUgdGhhdCBgX19TRU5UUllfX2AgaXMgdGhlcmUuCiAqKi8KZnVuY3Rpb24gZ2V0TWFpbkNhcnJpZXIoKSB7CiAgLy8gVGhpcyBlbnN1cmVzIGEgU2VudHJ5IGNhcnJpZXIgZXhpc3RzCiAgZ2V0U2VudHJ5Q2FycmllcihHTE9CQUxfT0JKKTsKICByZXR1cm4gR0xPQkFMX09CSjsKfQoKLyoqIFdpbGwgZWl0aGVyIGdldCB0aGUgZXhpc3Rpbmcgc2VudHJ5IGNhcnJpZXIsIG9yIGNyZWF0ZSBhIG5ldyBvbmUuICovCmZ1bmN0aW9uIGdldFNlbnRyeUNhcnJpZXIoY2FycmllcikgewogIGlmICghY2Fycmllci5fX1NFTlRSWV9fKSB7CiAgICBjYXJyaWVyLl9fU0VOVFJZX18gPSB7CiAgICAgIGV4dGVuc2lvbnM6IHt9LAogICAgfTsKICB9CiAgcmV0dXJuIGNhcnJpZXIuX19TRU5UUllfXzsKfQoKY29uc3QgREVGQVVMVF9FTlZJUk9OTUVOVCA9ICdwcm9kdWN0aW9uJzsKCi8qKgogKiBDcmVhdGVzIGEgbmV3IGBTZXNzaW9uYCBvYmplY3QgYnkgc2V0dGluZyBjZXJ0YWluIGRlZmF1bHQgcGFyYW1ldGVycy4gSWYgb3B0aW9uYWwgQHBhcmFtIGNvbnRleHQKICogaXMgcGFzc2VkLCB0aGUgcGFzc2VkIHByb3BlcnRpZXMgYXJlIGFwcGxpZWQgdG8gdGhlIHNlc3Npb24gb2JqZWN0LgogKgogKiBAcGFyYW0gY29udGV4dCAob3B0aW9uYWwpIGFkZGl0aW9uYWwgcHJvcGVydGllcyB0byBiZSBhcHBsaWVkIHRvIHRoZSByZXR1cm5lZCBzZXNzaW9uIG9iamVjdAogKgogKiBAcmV0dXJucyBhIG5ldyBgU2Vzc2lvbmAgb2JqZWN0CiAqLwpmdW5jdGlvbiBtYWtlU2Vzc2lvbihjb250ZXh0KSB7CiAgLy8gQm90aCB0aW1lc3RhbXAgYW5kIHN0YXJ0ZWQgYXJlIGluIHNlY29uZHMgc2luY2UgdGhlIFVOSVggZXBvY2guCiAgY29uc3Qgc3RhcnRpbmdUaW1lID0gdGltZXN0YW1wSW5TZWNvbmRzKCk7CgogIGNvbnN0IHNlc3Npb24gPSB7CiAgICBzaWQ6IHV1aWQ0KCksCiAgICBpbml0OiB0cnVlLAogICAgdGltZXN0YW1wOiBzdGFydGluZ1RpbWUsCiAgICBzdGFydGVkOiBzdGFydGluZ1RpbWUsCiAgICBkdXJhdGlvbjogMCwKICAgIHN0YXR1czogJ29rJywKICAgIGVycm9yczogMCwKICAgIGlnbm9yZUR1cmF0aW9uOiBmYWxzZSwKICAgIHRvSlNPTjogKCkgPT4gc2Vzc2lvblRvSlNPTihzZXNzaW9uKSwKICB9OwoKICBpZiAoY29udGV4dCkgewogICAgdXBkYXRlU2Vzc2lvbihzZXNzaW9uLCBjb250ZXh0KTsKICB9CgogIHJldHVybiBzZXNzaW9uOwp9CgovKioKICogVXBkYXRlcyBhIHNlc3Npb24gb2JqZWN0IHdpdGggdGhlIHByb3BlcnRpZXMgcGFzc2VkIGluIHRoZSBjb250ZXh0LgogKgogKiBOb3RlIHRoYXQgdGhpcyBmdW5jdGlvbiBtdXRhdGVzIHRoZSBwYXNzZWQgb2JqZWN0IGFuZCByZXR1cm5zIHZvaWQuCiAqIChIYWQgdG8gZG8gdGhpcyBpbnN0ZWFkIG9mIHJldHVybmluZyBhIG5ldyBhbmQgdXBkYXRlZCBzZXNzaW9uIGJlY2F1c2UgY2xvc2luZyBhbmQgc2VuZGluZyBhIHNlc3Npb24KICogbWFrZXMgYW4gdXBkYXRlIHRvIHRoZSBzZXNzaW9uIGFmdGVyIGl0IHdhcyBwYXNzZWQgdG8gdGhlIHNlbmRpbmcgbG9naWMuCiAqIEBzZWUgQmFzZUNsaWVudC5jYXB0dXJlU2Vzc2lvbiApCiAqCiAqIEBwYXJhbSBzZXNzaW9uIHRoZSBgU2Vzc2lvbmAgdG8gdXBkYXRlCiAqIEBwYXJhbSBjb250ZXh0IHRoZSBgU2Vzc2lvbkNvbnRleHRgIGhvbGRpbmcgdGhlIHByb3BlcnRpZXMgdGhhdCBzaG91bGQgYmUgdXBkYXRlZCBpbiBAcGFyYW0gc2Vzc2lvbgogKi8KLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGNvbXBsZXhpdHkKZnVuY3Rpb24gdXBkYXRlU2Vzc2lvbihzZXNzaW9uLCBjb250ZXh0ID0ge30pIHsKICBpZiAoY29udGV4dC51c2VyKSB7CiAgICBpZiAoIXNlc3Npb24uaXBBZGRyZXNzICYmIGNvbnRleHQudXNlci5pcF9hZGRyZXNzKSB7CiAgICAgIHNlc3Npb24uaXBBZGRyZXNzID0gY29udGV4dC51c2VyLmlwX2FkZHJlc3M7CiAgICB9CgogICAgaWYgKCFzZXNzaW9uLmRpZCAmJiAhY29udGV4dC5kaWQpIHsKICAgICAgc2Vzc2lvbi5kaWQgPSBjb250ZXh0LnVzZXIuaWQgfHwgY29udGV4dC51c2VyLmVtYWlsIHx8IGNvbnRleHQudXNlci51c2VybmFtZTsKICAgIH0KICB9CgogIHNlc3Npb24udGltZXN0YW1wID0gY29udGV4dC50aW1lc3RhbXAgfHwgdGltZXN0YW1wSW5TZWNvbmRzKCk7CgogIGlmIChjb250ZXh0LmFibm9ybWFsX21lY2hhbmlzbSkgewogICAgc2Vzc2lvbi5hYm5vcm1hbF9tZWNoYW5pc20gPSBjb250ZXh0LmFibm9ybWFsX21lY2hhbmlzbTsKICB9CgogIGlmIChjb250ZXh0Lmlnbm9yZUR1cmF0aW9uKSB7CiAgICBzZXNzaW9uLmlnbm9yZUR1cmF0aW9uID0gY29udGV4dC5pZ25vcmVEdXJhdGlvbjsKICB9CiAgaWYgKGNvbnRleHQuc2lkKSB7CiAgICAvLyBHb29kIGVub3VnaCB1dWlkIHZhbGlkYXRpb24uIOKAlCBLYW1pbAogICAgc2Vzc2lvbi5zaWQgPSBjb250ZXh0LnNpZC5sZW5ndGggPT09IDMyID8gY29udGV4dC5zaWQgOiB1dWlkNCgpOwogIH0KICBpZiAoY29udGV4dC5pbml0ICE9PSB1bmRlZmluZWQpIHsKICAgIHNlc3Npb24uaW5pdCA9IGNvbnRleHQuaW5pdDsKICB9CiAgaWYgKCFzZXNzaW9uLmRpZCAmJiBjb250ZXh0LmRpZCkgewogICAgc2Vzc2lvbi5kaWQgPSBgJHtjb250ZXh0LmRpZH1gOwogIH0KICBpZiAodHlwZW9mIGNvbnRleHQuc3RhcnRlZCA9PT0gJ251bWJlcicpIHsKICAgIHNlc3Npb24uc3RhcnRlZCA9IGNvbnRleHQuc3RhcnRlZDsKICB9CiAgaWYgKHNlc3Npb24uaWdub3JlRHVyYXRpb24pIHsKICAgIHNlc3Npb24uZHVyYXRpb24gPSB1bmRlZmluZWQ7CiAgfSBlbHNlIGlmICh0eXBlb2YgY29udGV4dC5kdXJhdGlvbiA9PT0gJ251bWJlcicpIHsKICAgIHNlc3Npb24uZHVyYXRpb24gPSBjb250ZXh0LmR1cmF0aW9uOwogIH0gZWxzZSB7CiAgICBjb25zdCBkdXJhdGlvbiA9IHNlc3Npb24udGltZXN0YW1wIC0gc2Vzc2lvbi5zdGFydGVkOwogICAgc2Vzc2lvbi5kdXJhdGlvbiA9IGR1cmF0aW9uID49IDAgPyBkdXJhdGlvbiA6IDA7CiAgfQogIGlmIChjb250ZXh0LnJlbGVhc2UpIHsKICAgIHNlc3Npb24ucmVsZWFzZSA9IGNvbnRleHQucmVsZWFzZTsKICB9CiAgaWYgKGNvbnRleHQuZW52aXJvbm1lbnQpIHsKICAgIHNlc3Npb24uZW52aXJvbm1lbnQgPSBjb250ZXh0LmVudmlyb25tZW50OwogIH0KICBpZiAoIXNlc3Npb24uaXBBZGRyZXNzICYmIGNvbnRleHQuaXBBZGRyZXNzKSB7CiAgICBzZXNzaW9uLmlwQWRkcmVzcyA9IGNvbnRleHQuaXBBZGRyZXNzOwogIH0KICBpZiAoIXNlc3Npb24udXNlckFnZW50ICYmIGNvbnRleHQudXNlckFnZW50KSB7CiAgICBzZXNzaW9uLnVzZXJBZ2VudCA9IGNvbnRleHQudXNlckFnZW50OwogIH0KICBpZiAodHlwZW9mIGNvbnRleHQuZXJyb3JzID09PSAnbnVtYmVyJykgewogICAgc2Vzc2lvbi5lcnJvcnMgPSBjb250ZXh0LmVycm9yczsKICB9CiAgaWYgKGNvbnRleHQuc3RhdHVzKSB7CiAgICBzZXNzaW9uLnN0YXR1cyA9IGNvbnRleHQuc3RhdHVzOwogIH0KfQoKLyoqCiAqIENsb3NlcyBhIHNlc3Npb24gYnkgc2V0dGluZyBpdHMgc3RhdHVzIGFuZCB1cGRhdGluZyB0aGUgc2Vzc2lvbiBvYmplY3Qgd2l0aCBpdC4KICogSW50ZXJuYWxseSBjYWxscyBgdXBkYXRlU2Vzc2lvbmAgdG8gdXBkYXRlIHRoZSBwYXNzZWQgc2Vzc2lvbiBvYmplY3QuCiAqCiAqIE5vdGUgdGhhdCB0aGlzIGZ1bmN0aW9uIG11dGF0ZXMgdGhlIHBhc3NlZCBzZXNzaW9uIChAc2VlIHVwZGF0ZVNlc3Npb24gZm9yIGV4cGxhbmF0aW9uKS4KICoKICogQHBhcmFtIHNlc3Npb24gdGhlIGBTZXNzaW9uYCBvYmplY3QgdG8gYmUgY2xvc2VkCiAqIEBwYXJhbSBzdGF0dXMgdGhlIGBTZXNzaW9uU3RhdHVzYCB3aXRoIHdoaWNoIHRoZSBzZXNzaW9uIHdhcyBjbG9zZWQuIElmIHlvdSBkb24ndCBwYXNzIGEgc3RhdHVzLAogKiAgICAgICAgICAgICAgIHRoaXMgZnVuY3Rpb24gd2lsbCBrZWVwIHRoZSBwcmV2aW91c2x5IHNldCBzdGF0dXMsIHVubGVzcyBpdCB3YXMgYCdvaydgIGluIHdoaWNoIGNhc2UKICogICAgICAgICAgICAgICBpdCBpcyBjaGFuZ2VkIHRvIGAnZXhpdGVkJ2AuCiAqLwpmdW5jdGlvbiBjbG9zZVNlc3Npb24oc2Vzc2lvbiwgc3RhdHVzKSB7CiAgbGV0IGNvbnRleHQgPSB7fTsKICBpZiAoc3RhdHVzKSB7CiAgICBjb250ZXh0ID0geyBzdGF0dXMgfTsKICB9IGVsc2UgaWYgKHNlc3Npb24uc3RhdHVzID09PSAnb2snKSB7CiAgICBjb250ZXh0ID0geyBzdGF0dXM6ICdleGl0ZWQnIH07CiAgfQoKICB1cGRhdGVTZXNzaW9uKHNlc3Npb24sIGNvbnRleHQpOwp9CgovKioKICogU2VyaWFsaXplcyBhIHBhc3NlZCBzZXNzaW9uIG9iamVjdCB0byBhIEpTT04gb2JqZWN0IHdpdGggYSBzbGlnaHRseSBkaWZmZXJlbnQgc3RydWN0dXJlLgogKiBUaGlzIGlzIG5lY2Vzc2FyeSBiZWNhdXNlIHRoZSBTZW50cnkgYmFja2VuZCByZXF1aXJlcyBhIHNsaWdodGx5IGRpZmZlcmVudCBzY2hlbWEgb2YgYSBzZXNzaW9uCiAqIHRoYW4gdGhlIG9uZSB0aGUgSlMgU0RLcyB1c2UgaW50ZXJuYWxseS4KICoKICogQHBhcmFtIHNlc3Npb24gdGhlIHNlc3Npb24gdG8gYmUgY29udmVydGVkCiAqCiAqIEByZXR1cm5zIGEgSlNPTiBvYmplY3Qgb2YgdGhlIHBhc3NlZCBzZXNzaW9uCiAqLwpmdW5jdGlvbiBzZXNzaW9uVG9KU09OKHNlc3Npb24pIHsKICByZXR1cm4gZHJvcFVuZGVmaW5lZEtleXMoewogICAgc2lkOiBgJHtzZXNzaW9uLnNpZH1gLAogICAgaW5pdDogc2Vzc2lvbi5pbml0LAogICAgLy8gTWFrZSBzdXJlIHRoYXQgc2VjIGlzIGNvbnZlcnRlZCB0byBtcyBmb3IgZGF0ZSBjb25zdHJ1Y3RvcgogICAgc3RhcnRlZDogbmV3IERhdGUoc2Vzc2lvbi5zdGFydGVkICogMTAwMCkudG9JU09TdHJpbmcoKSwKICAgIHRpbWVzdGFtcDogbmV3IERhdGUoc2Vzc2lvbi50aW1lc3RhbXAgKiAxMDAwKS50b0lTT1N0cmluZygpLAogICAgc3RhdHVzOiBzZXNzaW9uLnN0YXR1cywKICAgIGVycm9yczogc2Vzc2lvbi5lcnJvcnMsCiAgICBkaWQ6IHR5cGVvZiBzZXNzaW9uLmRpZCA9PT0gJ251bWJlcicgfHwgdHlwZW9mIHNlc3Npb24uZGlkID09PSAnc3RyaW5nJyA/IGAke3Nlc3Npb24uZGlkfWAgOiB1bmRlZmluZWQsCiAgICBkdXJhdGlvbjogc2Vzc2lvbi5kdXJhdGlvbiwKICAgIGFibm9ybWFsX21lY2hhbmlzbTogc2Vzc2lvbi5hYm5vcm1hbF9tZWNoYW5pc20sCiAgICBhdHRyczogewogICAgICByZWxlYXNlOiBzZXNzaW9uLnJlbGVhc2UsCiAgICAgIGVudmlyb25tZW50OiBzZXNzaW9uLmVudmlyb25tZW50LAogICAgICBpcF9hZGRyZXNzOiBzZXNzaW9uLmlwQWRkcmVzcywKICAgICAgdXNlcl9hZ2VudDogc2Vzc2lvbi51c2VyQWdlbnQsCiAgICB9LAogIH0pOwp9Cgpjb25zdCBTQ09QRV9TUEFOX0ZJRUxEID0gJ19zZW50cnlTcGFuJzsKCi8qKgogKiBTZXQgdGhlIGFjdGl2ZSBzcGFuIGZvciBhIGdpdmVuIHNjb3BlLgogKiBOT1RFOiBUaGlzIHNob3VsZCBOT1QgYmUgdXNlZCBkaXJlY3RseSwgYnV0IGlzIG9ubHkgdXNlZCBpbnRlcm5hbGx5IGJ5IHRoZSB0cmFjZSBtZXRob2RzLgogKi8KZnVuY3Rpb24gX3NldFNwYW5Gb3JTY29wZShzY29wZSwgc3BhbikgewogIGlmIChzcGFuKSB7CiAgICBhZGROb25FbnVtZXJhYmxlUHJvcGVydHkoc2NvcGUgLCBTQ09QRV9TUEFOX0ZJRUxELCBzcGFuKTsKICB9IGVsc2UgewogICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1keW5hbWljLWRlbGV0ZQogICAgZGVsZXRlIChzY29wZSApW1NDT1BFX1NQQU5fRklFTERdOwogIH0KfQoKLyoqCiAqIEdldCB0aGUgYWN0aXZlIHNwYW4gZm9yIGEgZ2l2ZW4gc2NvcGUuCiAqIE5PVEU6IFRoaXMgc2hvdWxkIE5PVCBiZSB1c2VkIGRpcmVjdGx5LCBidXQgaXMgb25seSB1c2VkIGludGVybmFsbHkgYnkgdGhlIHRyYWNlIG1ldGhvZHMuCiAqLwpmdW5jdGlvbiBfZ2V0U3BhbkZvclNjb3BlKHNjb3BlKSB7CiAgcmV0dXJuIHNjb3BlW1NDT1BFX1NQQU5fRklFTERdOwp9CgovKioKICogRGVmYXVsdCB2YWx1ZSBmb3IgbWF4aW11bSBudW1iZXIgb2YgYnJlYWRjcnVtYnMgYWRkZWQgdG8gYW4gZXZlbnQuCiAqLwpjb25zdCBERUZBVUxUX01BWF9CUkVBRENSVU1CUyA9IDEwMDsKCi8qKgogKiBIb2xkcyBhZGRpdGlvbmFsIGV2ZW50IGluZm9ybWF0aW9uLgogKi8KY2xhc3MgU2NvcGUgIHsKICAvKiogRmxhZyBpZiBub3RpZnlpbmcgaXMgaGFwcGVuaW5nLiAqLwoKICAvKiogQ2FsbGJhY2sgZm9yIGNsaWVudCB0byByZWNlaXZlIHNjb3BlIGNoYW5nZXMuICovCgogIC8qKiBDYWxsYmFjayBsaXN0IHRoYXQgd2lsbCBiZSBjYWxsZWQgZHVyaW5nIGV2ZW50IHByb2Nlc3NpbmcuICovCgogIC8qKiBBcnJheSBvZiBicmVhZGNydW1icy4gKi8KCiAgLyoqIFVzZXIgKi8KCiAgLyoqIFRhZ3MgKi8KCiAgLyoqIEV4dHJhICovCgogIC8qKiBDb250ZXh0cyAqLwoKICAvKiogQXR0YWNobWVudHMgKi8KCiAgLyoqIFByb3BhZ2F0aW9uIENvbnRleHQgZm9yIGRpc3RyaWJ1dGVkIHRyYWNpbmcgKi8KCiAgLyoqCiAgICogQSBwbGFjZSB0byBzdGFzaCBkYXRhIHdoaWNoIGlzIG5lZWRlZCBhdCBzb21lIHBvaW50IGluIHRoZSBTREsncyBldmVudCBwcm9jZXNzaW5nIHBpcGVsaW5lIGJ1dCB3aGljaCBzaG91bGRuJ3QgZ2V0CiAgICogc2VudCB0byBTZW50cnkKICAgKi8KCiAgLyoqIEZpbmdlcnByaW50ICovCgogIC8qKiBTZXZlcml0eSAqLwoKICAvKioKICAgKiBUcmFuc2FjdGlvbiBOYW1lCiAgICoKICAgKiBJTVBPUlRBTlQ6IFRoZSB0cmFuc2FjdGlvbiBuYW1lIG9uIHRoZSBzY29wZSBoYXMgbm90aGluZyB0byBkbyB3aXRoIHJvb3Qgc3BhbnMvdHJhbnNhY3Rpb24gb2JqZWN0cy4KICAgKiBJdCdzIHB1cnBvc2UgaXMgdG8gYXNzaWduIGEgdHJhbnNhY3Rpb24gdG8gdGhlIHNjb3BlIHRoYXQncyBhZGRlZCB0byBub24tdHJhbnNhY3Rpb24gZXZlbnRzLgogICAqLwoKICAvKiogU2Vzc2lvbiAqLwoKICAvKiogUmVxdWVzdCBNb2RlIFNlc3Npb24gU3RhdHVzICovCgogIC8qKiBUaGUgY2xpZW50IG9uIHRoaXMgc2NvcGUgKi8KCiAgLy8gTk9URTogQW55IGZpZWxkIHdoaWNoIGdldHMgYWRkZWQgaGVyZSBzaG91bGQgZ2V0IGFkZGVkIG5vdCBvbmx5IHRvIHRoZSBjb25zdHJ1Y3RvciBidXQgYWxzbyB0byB0aGUgYGNsb25lYCBtZXRob2QuCgogICBjb25zdHJ1Y3RvcigpIHsKICAgIHRoaXMuX25vdGlmeWluZ0xpc3RlbmVycyA9IGZhbHNlOwogICAgdGhpcy5fc2NvcGVMaXN0ZW5lcnMgPSBbXTsKICAgIHRoaXMuX2V2ZW50UHJvY2Vzc29ycyA9IFtdOwogICAgdGhpcy5fYnJlYWRjcnVtYnMgPSBbXTsKICAgIHRoaXMuX2F0dGFjaG1lbnRzID0gW107CiAgICB0aGlzLl91c2VyID0ge307CiAgICB0aGlzLl90YWdzID0ge307CiAgICB0aGlzLl9leHRyYSA9IHt9OwogICAgdGhpcy5fY29udGV4dHMgPSB7fTsKICAgIHRoaXMuX3Nka1Byb2Nlc3NpbmdNZXRhZGF0YSA9IHt9OwogICAgdGhpcy5fcHJvcGFnYXRpb25Db250ZXh0ID0gZ2VuZXJhdGVQcm9wYWdhdGlvbkNvbnRleHQoKTsKICB9CgogIC8qKgogICAqIEBpbmhlcml0RG9jCiAgICovCiAgIGNsb25lKCkgewogICAgY29uc3QgbmV3U2NvcGUgPSBuZXcgU2NvcGUoKTsKICAgIG5ld1Njb3BlLl9icmVhZGNydW1icyA9IFsuLi50aGlzLl9icmVhZGNydW1ic107CiAgICBuZXdTY29wZS5fdGFncyA9IHsgLi4udGhpcy5fdGFncyB9OwogICAgbmV3U2NvcGUuX2V4dHJhID0geyAuLi50aGlzLl9leHRyYSB9OwogICAgbmV3U2NvcGUuX2NvbnRleHRzID0geyAuLi50aGlzLl9jb250ZXh0cyB9OwogICAgbmV3U2NvcGUuX3VzZXIgPSB0aGlzLl91c2VyOwogICAgbmV3U2NvcGUuX2xldmVsID0gdGhpcy5fbGV2ZWw7CiAgICBuZXdTY29wZS5fc2Vzc2lvbiA9IHRoaXMuX3Nlc3Npb247CiAgICBuZXdTY29wZS5fdHJhbnNhY3Rpb25OYW1lID0gdGhpcy5fdHJhbnNhY3Rpb25OYW1lOwogICAgbmV3U2NvcGUuX2ZpbmdlcnByaW50ID0gdGhpcy5fZmluZ2VycHJpbnQ7CiAgICBuZXdTY29wZS5fZXZlbnRQcm9jZXNzb3JzID0gWy4uLnRoaXMuX2V2ZW50UHJvY2Vzc29yc107CiAgICBuZXdTY29wZS5fcmVxdWVzdFNlc3Npb24gPSB0aGlzLl9yZXF1ZXN0U2Vzc2lvbjsKICAgIG5ld1Njb3BlLl9hdHRhY2htZW50cyA9IFsuLi50aGlzLl9hdHRhY2htZW50c107CiAgICBuZXdTY29wZS5fc2RrUHJvY2Vzc2luZ01ldGFkYXRhID0geyAuLi50aGlzLl9zZGtQcm9jZXNzaW5nTWV0YWRhdGEgfTsKICAgIG5ld1Njb3BlLl9wcm9wYWdhdGlvbkNvbnRleHQgPSB7IC4uLnRoaXMuX3Byb3BhZ2F0aW9uQ29udGV4dCB9OwogICAgbmV3U2NvcGUuX2NsaWVudCA9IHRoaXMuX2NsaWVudDsKCiAgICBfc2V0U3BhbkZvclNjb3BlKG5ld1Njb3BlLCBfZ2V0U3BhbkZvclNjb3BlKHRoaXMpKTsKCiAgICByZXR1cm4gbmV3U2NvcGU7CiAgfQoKICAvKioKICAgKiBAaW5oZXJpdERvYwogICAqLwogICBzZXRDbGllbnQoY2xpZW50KSB7CiAgICB0aGlzLl9jbGllbnQgPSBjbGllbnQ7CiAgfQoKICAvKioKICAgKiBAaW5oZXJpdERvYwogICAqLwogICBnZXRDbGllbnQoKSB7CiAgICByZXR1cm4gdGhpcy5fY2xpZW50IDsKICB9CgogIC8qKgogICAqIEBpbmhlcml0RG9jCiAgICovCiAgIGFkZFNjb3BlTGlzdGVuZXIoY2FsbGJhY2spIHsKICAgIHRoaXMuX3Njb3BlTGlzdGVuZXJzLnB1c2goY2FsbGJhY2spOwogIH0KCiAgLyoqCiAgICogQGluaGVyaXREb2MKICAgKi8KICAgYWRkRXZlbnRQcm9jZXNzb3IoY2FsbGJhY2spIHsKICAgIHRoaXMuX2V2ZW50UHJvY2Vzc29ycy5wdXNoKGNhbGxiYWNrKTsKICAgIHJldHVybiB0aGlzOwogIH0KCiAgLyoqCiAgICogQGluaGVyaXREb2MKICAgKi8KICAgc2V0VXNlcih1c2VyKSB7CiAgICAvLyBJZiBudWxsIGlzIHBhc3NlZCB3ZSB3YW50IHRvIHVuc2V0IGV2ZXJ5dGhpbmcsIGJ1dCBzdGlsbCBkZWZpbmUga2V5cywKICAgIC8vIHNvIHRoYXQgbGF0ZXIgZG93biBpbiB0aGUgcGlwZWxpbmUgYW55IGV4aXN0aW5nIHZhbHVlcyBhcmUgY2xlYXJlZC4KICAgIHRoaXMuX3VzZXIgPSB1c2VyIHx8IHsKICAgICAgZW1haWw6IHVuZGVmaW5lZCwKICAgICAgaWQ6IHVuZGVmaW5lZCwKICAgICAgaXBfYWRkcmVzczogdW5kZWZpbmVkLAogICAgICB1c2VybmFtZTogdW5kZWZpbmVkLAogICAgfTsKCiAgICBpZiAodGhpcy5fc2Vzc2lvbikgewogICAgICB1cGRhdGVTZXNzaW9uKHRoaXMuX3Nlc3Npb24sIHsgdXNlciB9KTsKICAgIH0KCiAgICB0aGlzLl9ub3RpZnlTY29wZUxpc3RlbmVycygpOwogICAgcmV0dXJuIHRoaXM7CiAgfQoKICAvKioKICAgKiBAaW5oZXJpdERvYwogICAqLwogICBnZXRVc2VyKCkgewogICAgcmV0dXJuIHRoaXMuX3VzZXI7CiAgfQoKICAvKioKICAgKiBAaW5oZXJpdERvYwogICAqLwogICBnZXRSZXF1ZXN0U2Vzc2lvbigpIHsKICAgIHJldHVybiB0aGlzLl9yZXF1ZXN0U2Vzc2lvbjsKICB9CgogIC8qKgogICAqIEBpbmhlcml0RG9jCiAgICovCiAgIHNldFJlcXVlc3RTZXNzaW9uKHJlcXVlc3RTZXNzaW9uKSB7CiAgICB0aGlzLl9yZXF1ZXN0U2Vzc2lvbiA9IHJlcXVlc3RTZXNzaW9uOwogICAgcmV0dXJuIHRoaXM7CiAgfQoKICAvKioKICAgKiBAaW5oZXJpdERvYwogICAqLwogICBzZXRUYWdzKHRhZ3MpIHsKICAgIHRoaXMuX3RhZ3MgPSB7CiAgICAgIC4uLnRoaXMuX3RhZ3MsCiAgICAgIC4uLnRhZ3MsCiAgICB9OwogICAgdGhpcy5fbm90aWZ5U2NvcGVMaXN0ZW5lcnMoKTsKICAgIHJldHVybiB0aGlzOwogIH0KCiAgLyoqCiAgICogQGluaGVyaXREb2MKICAgKi8KICAgc2V0VGFnKGtleSwgdmFsdWUpIHsKICAgIHRoaXMuX3RhZ3MgPSB7IC4uLnRoaXMuX3RhZ3MsIFtrZXldOiB2YWx1ZSB9OwogICAgdGhpcy5fbm90aWZ5U2NvcGVMaXN0ZW5lcnMoKTsKICAgIHJldHVybiB0aGlzOwogIH0KCiAgLyoqCiAgICogQGluaGVyaXREb2MKICAgKi8KICAgc2V0RXh0cmFzKGV4dHJhcykgewogICAgdGhpcy5fZXh0cmEgPSB7CiAgICAgIC4uLnRoaXMuX2V4dHJhLAogICAgICAuLi5leHRyYXMsCiAgICB9OwogICAgdGhpcy5fbm90aWZ5U2NvcGVMaXN0ZW5lcnMoKTsKICAgIHJldHVybiB0aGlzOwogIH0KCiAgLyoqCiAgICogQGluaGVyaXREb2MKICAgKi8KICAgc2V0RXh0cmEoa2V5LCBleHRyYSkgewogICAgdGhpcy5fZXh0cmEgPSB7IC4uLnRoaXMuX2V4dHJhLCBba2V5XTogZXh0cmEgfTsKICAgIHRoaXMuX25vdGlmeVNjb3BlTGlzdGVuZXJzKCk7CiAgICByZXR1cm4gdGhpczsKICB9CgogIC8qKgogICAqIEBpbmhlcml0RG9jCiAgICovCiAgIHNldEZpbmdlcnByaW50KGZpbmdlcnByaW50KSB7CiAgICB0aGlzLl9maW5nZXJwcmludCA9IGZpbmdlcnByaW50OwogICAgdGhpcy5fbm90aWZ5U2NvcGVMaXN0ZW5lcnMoKTsKICAgIHJldHVybiB0aGlzOwogIH0KCiAgLyoqCiAgICogQGluaGVyaXREb2MKICAgKi8KICAgc2V0TGV2ZWwobGV2ZWwpIHsKICAgIHRoaXMuX2xldmVsID0gbGV2ZWw7CiAgICB0aGlzLl9ub3RpZnlTY29wZUxpc3RlbmVycygpOwogICAgcmV0dXJuIHRoaXM7CiAgfQoKICAvKioKICAgKiBAaW5oZXJpdERvYwogICAqLwogICBzZXRUcmFuc2FjdGlvbk5hbWUobmFtZSkgewogICAgdGhpcy5fdHJhbnNhY3Rpb25OYW1lID0gbmFtZTsKICAgIHRoaXMuX25vdGlmeVNjb3BlTGlzdGVuZXJzKCk7CiAgICByZXR1cm4gdGhpczsKICB9CgogIC8qKgogICAqIEBpbmhlcml0RG9jCiAgICovCiAgIHNldENvbnRleHQoa2V5LCBjb250ZXh0KSB7CiAgICBpZiAoY29udGV4dCA9PT0gbnVsbCkgewogICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWR5bmFtaWMtZGVsZXRlCiAgICAgIGRlbGV0ZSB0aGlzLl9jb250ZXh0c1trZXldOwogICAgfSBlbHNlIHsKICAgICAgdGhpcy5fY29udGV4dHNba2V5XSA9IGNvbnRleHQ7CiAgICB9CgogICAgdGhpcy5fbm90aWZ5U2NvcGVMaXN0ZW5lcnMoKTsKICAgIHJldHVybiB0aGlzOwogIH0KCiAgLyoqCiAgICogQGluaGVyaXREb2MKICAgKi8KICAgc2V0U2Vzc2lvbihzZXNzaW9uKSB7CiAgICBpZiAoIXNlc3Npb24pIHsKICAgICAgZGVsZXRlIHRoaXMuX3Nlc3Npb247CiAgICB9IGVsc2UgewogICAgICB0aGlzLl9zZXNzaW9uID0gc2Vzc2lvbjsKICAgIH0KICAgIHRoaXMuX25vdGlmeVNjb3BlTGlzdGVuZXJzKCk7CiAgICByZXR1cm4gdGhpczsKICB9CgogIC8qKgogICAqIEBpbmhlcml0RG9jCiAgICovCiAgIGdldFNlc3Npb24oKSB7CiAgICByZXR1cm4gdGhpcy5fc2Vzc2lvbjsKICB9CgogIC8qKgogICAqIEBpbmhlcml0RG9jCiAgICovCiAgIHVwZGF0ZShjYXB0dXJlQ29udGV4dCkgewogICAgaWYgKCFjYXB0dXJlQ29udGV4dCkgewogICAgICByZXR1cm4gdGhpczsKICAgIH0KCiAgICBjb25zdCBzY29wZVRvTWVyZ2UgPSB0eXBlb2YgY2FwdHVyZUNvbnRleHQgPT09ICdmdW5jdGlvbicgPyBjYXB0dXJlQ29udGV4dCh0aGlzKSA6IGNhcHR1cmVDb250ZXh0OwoKICAgIGNvbnN0IFtzY29wZUluc3RhbmNlLCByZXF1ZXN0U2Vzc2lvbl0gPQogICAgICBzY29wZVRvTWVyZ2UgaW5zdGFuY2VvZiBTY29wZQogICAgICAgID8gW3Njb3BlVG9NZXJnZS5nZXRTY29wZURhdGEoKSwgc2NvcGVUb01lcmdlLmdldFJlcXVlc3RTZXNzaW9uKCldCiAgICAgICAgOiBpc1BsYWluT2JqZWN0KHNjb3BlVG9NZXJnZSkKICAgICAgICAgID8gW2NhcHR1cmVDb250ZXh0ICwgKGNhcHR1cmVDb250ZXh0ICkucmVxdWVzdFNlc3Npb25dCiAgICAgICAgICA6IFtdOwoKICAgIGNvbnN0IHsgdGFncywgZXh0cmEsIHVzZXIsIGNvbnRleHRzLCBsZXZlbCwgZmluZ2VycHJpbnQgPSBbXSwgcHJvcGFnYXRpb25Db250ZXh0IH0gPSBzY29wZUluc3RhbmNlIHx8IHt9OwoKICAgIHRoaXMuX3RhZ3MgPSB7IC4uLnRoaXMuX3RhZ3MsIC4uLnRhZ3MgfTsKICAgIHRoaXMuX2V4dHJhID0geyAuLi50aGlzLl9leHRyYSwgLi4uZXh0cmEgfTsKICAgIHRoaXMuX2NvbnRleHRzID0geyAuLi50aGlzLl9jb250ZXh0cywgLi4uY29udGV4dHMgfTsKCiAgICBpZiAodXNlciAmJiBPYmplY3Qua2V5cyh1c2VyKS5sZW5ndGgpIHsKICAgICAgdGhpcy5fdXNlciA9IHVzZXI7CiAgICB9CgogICAgaWYgKGxldmVsKSB7CiAgICAgIHRoaXMuX2xldmVsID0gbGV2ZWw7CiAgICB9CgogICAgaWYgKGZpbmdlcnByaW50Lmxlbmd0aCkgewogICAgICB0aGlzLl9maW5nZXJwcmludCA9IGZpbmdlcnByaW50OwogICAgfQoKICAgIGlmIChwcm9wYWdhdGlvbkNvbnRleHQpIHsKICAgICAgdGhpcy5fcHJvcGFnYXRpb25Db250ZXh0ID0gcHJvcGFnYXRpb25Db250ZXh0OwogICAgfQoKICAgIGlmIChyZXF1ZXN0U2Vzc2lvbikgewogICAgICB0aGlzLl9yZXF1ZXN0U2Vzc2lvbiA9IHJlcXVlc3RTZXNzaW9uOwogICAgfQoKICAgIHJldHVybiB0aGlzOwogIH0KCiAgLyoqCiAgICogQGluaGVyaXREb2MKICAgKi8KICAgY2xlYXIoKSB7CiAgICAvLyBjbGllbnQgaXMgbm90IGNsZWFyZWQgaGVyZSBvbiBwdXJwb3NlIQogICAgdGhpcy5fYnJlYWRjcnVtYnMgPSBbXTsKICAgIHRoaXMuX3RhZ3MgPSB7fTsKICAgIHRoaXMuX2V4dHJhID0ge307CiAgICB0aGlzLl91c2VyID0ge307CiAgICB0aGlzLl9jb250ZXh0cyA9IHt9OwogICAgdGhpcy5fbGV2ZWwgPSB1bmRlZmluZWQ7CiAgICB0aGlzLl90cmFuc2FjdGlvbk5hbWUgPSB1bmRlZmluZWQ7CiAgICB0aGlzLl9maW5nZXJwcmludCA9IHVuZGVmaW5lZDsKICAgIHRoaXMuX3JlcXVlc3RTZXNzaW9uID0gdW5kZWZpbmVkOwogICAgdGhpcy5fc2Vzc2lvbiA9IHVuZGVmaW5lZDsKICAgIF9zZXRTcGFuRm9yU2NvcGUodGhpcywgdW5kZWZpbmVkKTsKICAgIHRoaXMuX2F0dGFjaG1lbnRzID0gW107CiAgICB0aGlzLl9wcm9wYWdhdGlvbkNvbnRleHQgPSBnZW5lcmF0ZVByb3BhZ2F0aW9uQ29udGV4dCgpOwoKICAgIHRoaXMuX25vdGlmeVNjb3BlTGlzdGVuZXJzKCk7CiAgICByZXR1cm4gdGhpczsKICB9CgogIC8qKgogICAqIEBpbmhlcml0RG9jCiAgICovCiAgIGFkZEJyZWFkY3J1bWIoYnJlYWRjcnVtYiwgbWF4QnJlYWRjcnVtYnMpIHsKICAgIGNvbnN0IG1heENydW1icyA9IHR5cGVvZiBtYXhCcmVhZGNydW1icyA9PT0gJ251bWJlcicgPyBtYXhCcmVhZGNydW1icyA6IERFRkFVTFRfTUFYX0JSRUFEQ1JVTUJTOwoKICAgIC8vIE5vIGRhdGEgaGFzIGJlZW4gY2hhbmdlZCwgc28gZG9uJ3Qgbm90aWZ5IHNjb3BlIGxpc3RlbmVycwogICAgaWYgKG1heENydW1icyA8PSAwKSB7CiAgICAgIHJldHVybiB0aGlzOwogICAgfQoKICAgIGNvbnN0IG1lcmdlZEJyZWFkY3J1bWIgPSB7CiAgICAgIHRpbWVzdGFtcDogZGF0ZVRpbWVzdGFtcEluU2Vjb25kcygpLAogICAgICAuLi5icmVhZGNydW1iLAogICAgfTsKCiAgICBjb25zdCBicmVhZGNydW1icyA9IHRoaXMuX2JyZWFkY3J1bWJzOwogICAgYnJlYWRjcnVtYnMucHVzaChtZXJnZWRCcmVhZGNydW1iKTsKICAgIHRoaXMuX2JyZWFkY3J1bWJzID0gYnJlYWRjcnVtYnMubGVuZ3RoID4gbWF4Q3J1bWJzID8gYnJlYWRjcnVtYnMuc2xpY2UoLW1heENydW1icykgOiBicmVhZGNydW1iczsKCiAgICB0aGlzLl9ub3RpZnlTY29wZUxpc3RlbmVycygpOwoKICAgIHJldHVybiB0aGlzOwogIH0KCiAgLyoqCiAgICogQGluaGVyaXREb2MKICAgKi8KICAgZ2V0TGFzdEJyZWFkY3J1bWIoKSB7CiAgICByZXR1cm4gdGhpcy5fYnJlYWRjcnVtYnNbdGhpcy5fYnJlYWRjcnVtYnMubGVuZ3RoIC0gMV07CiAgfQoKICAvKioKICAgKiBAaW5oZXJpdERvYwogICAqLwogICBjbGVhckJyZWFkY3J1bWJzKCkgewogICAgdGhpcy5fYnJlYWRjcnVtYnMgPSBbXTsKICAgIHRoaXMuX25vdGlmeVNjb3BlTGlzdGVuZXJzKCk7CiAgICByZXR1cm4gdGhpczsKICB9CgogIC8qKgogICAqIEBpbmhlcml0RG9jCiAgICovCiAgIGFkZEF0dGFjaG1lbnQoYXR0YWNobWVudCkgewogICAgdGhpcy5fYXR0YWNobWVudHMucHVzaChhdHRhY2htZW50KTsKICAgIHJldHVybiB0aGlzOwogIH0KCiAgLyoqCiAgICogQGluaGVyaXREb2MKICAgKi8KICAgY2xlYXJBdHRhY2htZW50cygpIHsKICAgIHRoaXMuX2F0dGFjaG1lbnRzID0gW107CiAgICByZXR1cm4gdGhpczsKICB9CgogIC8qKiBAaW5oZXJpdERvYyAqLwogICBnZXRTY29wZURhdGEoKSB7CiAgICByZXR1cm4gewogICAgICBicmVhZGNydW1iczogdGhpcy5fYnJlYWRjcnVtYnMsCiAgICAgIGF0dGFjaG1lbnRzOiB0aGlzLl9hdHRhY2htZW50cywKICAgICAgY29udGV4dHM6IHRoaXMuX2NvbnRleHRzLAogICAgICB0YWdzOiB0aGlzLl90YWdzLAogICAgICBleHRyYTogdGhpcy5fZXh0cmEsCiAgICAgIHVzZXI6IHRoaXMuX3VzZXIsCiAgICAgIGxldmVsOiB0aGlzLl9sZXZlbCwKICAgICAgZmluZ2VycHJpbnQ6IHRoaXMuX2ZpbmdlcnByaW50IHx8IFtdLAogICAgICBldmVudFByb2Nlc3NvcnM6IHRoaXMuX2V2ZW50UHJvY2Vzc29ycywKICAgICAgcHJvcGFnYXRpb25Db250ZXh0OiB0aGlzLl9wcm9wYWdhdGlvbkNvbnRleHQsCiAgICAgIHNka1Byb2Nlc3NpbmdNZXRhZGF0YTogdGhpcy5fc2RrUHJvY2Vzc2luZ01ldGFkYXRhLAogICAgICB0cmFuc2FjdGlvbk5hbWU6IHRoaXMuX3RyYW5zYWN0aW9uTmFtZSwKICAgICAgc3BhbjogX2dldFNwYW5Gb3JTY29wZSh0aGlzKSwKICAgIH07CiAgfQoKICAvKioKICAgKiBAaW5oZXJpdERvYwogICAqLwogICBzZXRTREtQcm9jZXNzaW5nTWV0YWRhdGEobmV3RGF0YSkgewogICAgdGhpcy5fc2RrUHJvY2Vzc2luZ01ldGFkYXRhID0geyAuLi50aGlzLl9zZGtQcm9jZXNzaW5nTWV0YWRhdGEsIC4uLm5ld0RhdGEgfTsKCiAgICByZXR1cm4gdGhpczsKICB9CgogIC8qKgogICAqIEBpbmhlcml0RG9jCiAgICovCiAgIHNldFByb3BhZ2F0aW9uQ29udGV4dChjb250ZXh0KSB7CiAgICB0aGlzLl9wcm9wYWdhdGlvbkNvbnRleHQgPSBjb250ZXh0OwogICAgcmV0dXJuIHRoaXM7CiAgfQoKICAvKioKICAgKiBAaW5oZXJpdERvYwogICAqLwogICBnZXRQcm9wYWdhdGlvbkNvbnRleHQoKSB7CiAgICByZXR1cm4gdGhpcy5fcHJvcGFnYXRpb25Db250ZXh0OwogIH0KCiAgLyoqCiAgICogQGluaGVyaXREb2MKICAgKi8KICAgY2FwdHVyZUV4Y2VwdGlvbihleGNlcHRpb24sIGhpbnQpIHsKICAgIGNvbnN0IGV2ZW50SWQgPSBoaW50ICYmIGhpbnQuZXZlbnRfaWQgPyBoaW50LmV2ZW50X2lkIDogdXVpZDQoKTsKCiAgICBpZiAoIXRoaXMuX2NsaWVudCkgewogICAgICBsb2dnZXIud2FybignTm8gY2xpZW50IGNvbmZpZ3VyZWQgb24gc2NvcGUgLSB3aWxsIG5vdCBjYXB0dXJlIGV4Y2VwdGlvbiEnKTsKICAgICAgcmV0dXJuIGV2ZW50SWQ7CiAgICB9CgogICAgY29uc3Qgc3ludGhldGljRXhjZXB0aW9uID0gbmV3IEVycm9yKCdTZW50cnkgc3ludGhldGljRXhjZXB0aW9uJyk7CgogICAgdGhpcy5fY2xpZW50LmNhcHR1cmVFeGNlcHRpb24oCiAgICAgIGV4Y2VwdGlvbiwKICAgICAgewogICAgICAgIG9yaWdpbmFsRXhjZXB0aW9uOiBleGNlcHRpb24sCiAgICAgICAgc3ludGhldGljRXhjZXB0aW9uLAogICAgICAgIC4uLmhpbnQsCiAgICAgICAgZXZlbnRfaWQ6IGV2ZW50SWQsCiAgICAgIH0sCiAgICAgIHRoaXMsCiAgICApOwoKICAgIHJldHVybiBldmVudElkOwogIH0KCiAgLyoqCiAgICogQGluaGVyaXREb2MKICAgKi8KICAgY2FwdHVyZU1lc3NhZ2UobWVzc2FnZSwgbGV2ZWwsIGhpbnQpIHsKICAgIGNvbnN0IGV2ZW50SWQgPSBoaW50ICYmIGhpbnQuZXZlbnRfaWQgPyBoaW50LmV2ZW50X2lkIDogdXVpZDQoKTsKCiAgICBpZiAoIXRoaXMuX2NsaWVudCkgewogICAgICBsb2dnZXIud2FybignTm8gY2xpZW50IGNvbmZpZ3VyZWQgb24gc2NvcGUgLSB3aWxsIG5vdCBjYXB0dXJlIG1lc3NhZ2UhJyk7CiAgICAgIHJldHVybiBldmVudElkOwogICAgfQoKICAgIGNvbnN0IHN5bnRoZXRpY0V4Y2VwdGlvbiA9IG5ldyBFcnJvcihtZXNzYWdlKTsKCiAgICB0aGlzLl9jbGllbnQuY2FwdHVyZU1lc3NhZ2UoCiAgICAgIG1lc3NhZ2UsCiAgICAgIGxldmVsLAogICAgICB7CiAgICAgICAgb3JpZ2luYWxFeGNlcHRpb246IG1lc3NhZ2UsCiAgICAgICAgc3ludGhldGljRXhjZXB0aW9uLAogICAgICAgIC4uLmhpbnQsCiAgICAgICAgZXZlbnRfaWQ6IGV2ZW50SWQsCiAgICAgIH0sCiAgICAgIHRoaXMsCiAgICApOwoKICAgIHJldHVybiBldmVudElkOwogIH0KCiAgLyoqCiAgICogQGluaGVyaXREb2MKICAgKi8KICAgY2FwdHVyZUV2ZW50KGV2ZW50LCBoaW50KSB7CiAgICBjb25zdCBldmVudElkID0gaGludCAmJiBoaW50LmV2ZW50X2lkID8gaGludC5ldmVudF9pZCA6IHV1aWQ0KCk7CgogICAgaWYgKCF0aGlzLl9jbGllbnQpIHsKICAgICAgbG9nZ2VyLndhcm4oJ05vIGNsaWVudCBjb25maWd1cmVkIG9uIHNjb3BlIC0gd2lsbCBub3QgY2FwdHVyZSBldmVudCEnKTsKICAgICAgcmV0dXJuIGV2ZW50SWQ7CiAgICB9CgogICAgdGhpcy5fY2xpZW50LmNhcHR1cmVFdmVudChldmVudCwgeyAuLi5oaW50LCBldmVudF9pZDogZXZlbnRJZCB9LCB0aGlzKTsKCiAgICByZXR1cm4gZXZlbnRJZDsKICB9CgogIC8qKgogICAqIFRoaXMgd2lsbCBiZSBjYWxsZWQgb24gZXZlcnkgc2V0IGNhbGwuCiAgICovCiAgIF9ub3RpZnlTY29wZUxpc3RlbmVycygpIHsKICAgIC8vIFdlIG5lZWQgdGhpcyBjaGVjayBmb3IgdGhpcy5fbm90aWZ5aW5nTGlzdGVuZXJzIHRvIGJlIGFibGUgdG8gd29yayBvbiBzY29wZSBkdXJpbmcgdXBkYXRlcwogICAgLy8gSWYgdGhpcyBjaGVjayBpcyBub3QgaGVyZSB3ZSdsbCBwcm9kdWNlIGVuZGxlc3MgcmVjdXJzaW9uIHdoZW4gc29tZXRoaW5nIGlzIGRvbmUgd2l0aCB0aGUgc2NvcGUKICAgIC8vIGR1cmluZyB0aGUgY2FsbGJhY2suCiAgICBpZiAoIXRoaXMuX25vdGlmeWluZ0xpc3RlbmVycykgewogICAgICB0aGlzLl9ub3RpZnlpbmdMaXN0ZW5lcnMgPSB0cnVlOwogICAgICB0aGlzLl9zY29wZUxpc3RlbmVycy5mb3JFYWNoKGNhbGxiYWNrID0+IHsKICAgICAgICBjYWxsYmFjayh0aGlzKTsKICAgICAgfSk7CiAgICAgIHRoaXMuX25vdGlmeWluZ0xpc3RlbmVycyA9IGZhbHNlOwogICAgfQogIH0KfQoKZnVuY3Rpb24gZ2VuZXJhdGVQcm9wYWdhdGlvbkNvbnRleHQoKSB7CiAgcmV0dXJuIHsKICAgIHRyYWNlSWQ6IHV1aWQ0KCksCiAgICBzcGFuSWQ6IHV1aWQ0KCkuc3Vic3RyaW5nKDE2KSwKICB9Owp9Cgpjb25zdCBTREtfVkVSU0lPTiA9ICc4LjAuMC1iZXRhLjEnOwoKLyoqCiAqIEFQSSBjb21wYXRpYmlsaXR5IHZlcnNpb24gb2YgdGhpcyBodWIuCiAqCiAqIFdBUk5JTkc6IFRoaXMgbnVtYmVyIHNob3VsZCBvbmx5IGJlIGluY3JlYXNlZCB3aGVuIHRoZSBnbG9iYWwgaW50ZXJmYWNlCiAqIGNoYW5nZXMgYW5kIG5ldyBtZXRob2RzIGFyZSBpbnRyb2R1Y2VkLgogKgogKiBAaGlkZGVuCiAqLwpjb25zdCBBUElfVkVSU0lPTiA9IHBhcnNlRmxvYXQoU0RLX1ZFUlNJT04pOwoKLyoqCiAqIERlZmF1bHQgbWF4aW11bSBudW1iZXIgb2YgYnJlYWRjcnVtYnMgYWRkZWQgdG8gYW4gZXZlbnQuIENhbiBiZSBvdmVyd3JpdHRlbgogKiB3aXRoIHtAbGluayBPcHRpb25zLm1heEJyZWFkY3J1bWJzfS4KICovCmNvbnN0IERFRkFVTFRfQlJFQURDUlVNQlMgPSAxMDA7CgovKioKICogQSBsYXllciBpbiB0aGUgcHJvY2VzcyBzdGFjay4KICogQGhpZGRlbgogKi8KCi8qKgogKiBAaW5oZXJpdERvYwogKiBAZGVwcmVjYXRlZCBUaGlzIGNsYXNzIHdpbGwgYmUgcmVtb3ZlZCBpbiB2OCAodG1wLWRlcHJlY2F0aW5nIHNvIHdlJ3JlIGF3YXJlIG9mIHdoZXJlIHRoaXMgaXMgYSBwcm9ibGVtKQogKi8KLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGRlcHJlY2F0aW9uL2RlcHJlY2F0aW9uCmNsYXNzIEh1YiAgewogIC8qKiBJcyBhIHtAbGluayBMYXllcn1bXSBjb250YWluaW5nIHRoZSBjbGllbnQgYW5kIHNjb3BlICovCgogIC8qKgogICAqIENyZWF0ZXMgYSBuZXcgaW5zdGFuY2Ugb2YgdGhlIGh1Yiwgd2lsbCBwdXNoIG9uZSB7QGxpbmsgTGF5ZXJ9IGludG8gdGhlCiAgICogaW50ZXJuYWwgc3RhY2sgb24gY3JlYXRpb24uCiAgICoKICAgKiBAcGFyYW0gY2xpZW50IGJvdW5kIHRvIHRoZSBodWIuCiAgICogQHBhcmFtIHNjb3BlIGJvdW5kIHRvIHRoZSBodWIuCiAgICogQHBhcmFtIHZlcnNpb24gbnVtYmVyLCBoaWdoZXIgbnVtYmVyIG1lYW5zIGhpZ2hlciBwcmlvcml0eS4KICAgKgogICAqIEBkZXByZWNhdGVkIEluc3RhbnRpYXRpb24gb2YgSHViIG9iamVjdHMgaXMgZGVwcmVjYXRlZCBhbmQgdGhlIGNvbnN0cnVjdG9yIHdpbGwgYmUgcmVtb3ZlZCBpbiB2ZXJzaW9uIDggb2YgdGhlIFNESy4KICAgKgogICAqIElmIHlvdSBhcmUgY3VycmVudGx5IHVzaW5nIHRoZSBIdWIgZm9yIG11bHRpLWNsaWVudCB1c2UgbGlrZSBzbzoKICAgKgogICAqIGBgYAogICAqIC8vIE9MRAogICAqIGNvbnN0IGh1YiA9IG5ldyBIdWIoKTsKICAgKiBodWIuYmluZENsaWVudChjbGllbnQpOwogICAqIG1ha2VNYWluKGh1YikKICAgKiBgYGAKICAgKgogICAqIGluc3RlYWQgaW5pdGlhbGl6ZSB0aGUgY2xpZW50IGFzIGZvbGxvd3M6CiAgICoKICAgKiBgYGAKICAgKiAvLyBORVcKICAgKiBTZW50cnkud2l0aElzb2xhdGlvblNjb3BlKCgpID0+IHsKICAgKiAgICBTZW50cnkuc2V0Q3VycmVudENsaWVudChjbGllbnQpOwogICAqICAgIGNsaWVudC5pbml0KCk7CiAgICogfSk7CiAgICogYGBgCiAgICoKICAgKiBJZiB5b3UgYXJlIHVzaW5nIHRoZSBIdWIgdG8gY2FwdHVyZSBldmVudHMgbGlrZSBzbzoKICAgKgogICAqIGBgYAogICAqIC8vIE9MRAogICAqIGNvbnN0IGNsaWVudCA9IG5ldyBDbGllbnQoKTsKICAgKiBjb25zdCBodWIgPSBuZXcgSHViKGNsaWVudCk7CiAgICogaHViLmNhcHR1cmVFeGNlcHRpb24oKQogICAqIGBgYAogICAqCiAgICogaW5zdGVhZCBjYXB0dXJlIGlzb2xhdGVkIGV2ZW50cyBhcyBmb2xsb3dzOgogICAqCiAgICogYGBgCiAgICogLy8gTkVXCiAgICogY29uc3QgY2xpZW50ID0gbmV3IENsaWVudCgpOwogICAqIGNvbnN0IHNjb3BlID0gbmV3IFNjb3BlKCk7CiAgICogc2NvcGUuc2V0Q2xpZW50KGNsaWVudCk7CiAgICogc2NvcGUuY2FwdHVyZUV4Y2VwdGlvbigpOwogICAqIGBgYAogICAqLwogICBjb25zdHJ1Y3RvcigKICAgIGNsaWVudCwKICAgIHNjb3BlLAogICAgaXNvbGF0aW9uU2NvcGUsCiAgICAgIF92ZXJzaW9uID0gQVBJX1ZFUlNJT04sCiAgKSB7dGhpcy5fdmVyc2lvbiA9IF92ZXJzaW9uOwogICAgbGV0IGFzc2lnbmVkU2NvcGU7CiAgICBpZiAoIXNjb3BlKSB7CiAgICAgIGFzc2lnbmVkU2NvcGUgPSBuZXcgU2NvcGUoKTsKICAgICAgYXNzaWduZWRTY29wZS5zZXRDbGllbnQoY2xpZW50KTsKICAgIH0gZWxzZSB7CiAgICAgIGFzc2lnbmVkU2NvcGUgPSBzY29wZTsKICAgIH0KCiAgICBsZXQgYXNzaWduZWRJc29sYXRpb25TY29wZTsKICAgIGlmICghaXNvbGF0aW9uU2NvcGUpIHsKICAgICAgYXNzaWduZWRJc29sYXRpb25TY29wZSA9IG5ldyBTY29wZSgpOwogICAgICBhc3NpZ25lZElzb2xhdGlvblNjb3BlLnNldENsaWVudChjbGllbnQpOwogICAgfSBlbHNlIHsKICAgICAgYXNzaWduZWRJc29sYXRpb25TY29wZSA9IGlzb2xhdGlvblNjb3BlOwogICAgfQoKICAgIHRoaXMuX3N0YWNrID0gW3sgc2NvcGU6IGFzc2lnbmVkU2NvcGUgfV07CgogICAgaWYgKGNsaWVudCkgewogICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgZGVwcmVjYXRpb24vZGVwcmVjYXRpb24KICAgICAgdGhpcy5iaW5kQ2xpZW50KGNsaWVudCk7CiAgICB9CgogICAgdGhpcy5faXNvbGF0aW9uU2NvcGUgPSBhc3NpZ25lZElzb2xhdGlvblNjb3BlOwogIH0KCiAgLyoqCiAgICogVGhpcyBiaW5kcyB0aGUgZ2l2ZW4gY2xpZW50IHRvIHRoZSBjdXJyZW50IHNjb3BlLgogICAqIEBwYXJhbSBjbGllbnQgQW4gU0RLIGNsaWVudCAoY2xpZW50KSBpbnN0YW5jZS4KICAgKgogICAqIEBkZXByZWNhdGVkIFVzZSBgaW5pdEFuZEJpbmQoKWAgZGlyZWN0bHksIG9yIGBzZXRDdXJyZW50Q2xpZW50KClgIGFuZC9vciBgY2xpZW50LmluaXQoKWAgaW5zdGVhZC4KICAgKi8KICAgYmluZENsaWVudChjbGllbnQpIHsKICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBkZXByZWNhdGlvbi9kZXByZWNhdGlvbgogICAgY29uc3QgdG9wID0gdGhpcy5nZXRTdGFja1RvcCgpOwogICAgdG9wLmNsaWVudCA9IGNsaWVudDsKICAgIHRvcC5zY29wZS5zZXRDbGllbnQoY2xpZW50KTsKICAgIGlmIChjbGllbnQpIHsKICAgICAgY2xpZW50LmluaXQoKTsKICAgIH0KICB9CgogIC8qKgogICAqIEBpbmhlcml0RG9jCiAgICoKICAgKiBAZGVwcmVjYXRlZCBVc2UgYFNlbnRyeS53aXRoU2NvcGUoKWAgaW5zdGVhZC4KICAgKi8KICAgd2l0aFNjb3BlKGNhbGxiYWNrKSB7CiAgICBjb25zdCBzY29wZSA9IHRoaXMuX3B1c2hTY29wZSgpOwoKICAgIGxldCBtYXliZVByb21pc2VSZXN1bHQ7CiAgICB0cnkgewogICAgICBtYXliZVByb21pc2VSZXN1bHQgPSBjYWxsYmFjayhzY29wZSk7CiAgICB9IGNhdGNoIChlKSB7CiAgICAgIHRoaXMuX3BvcFNjb3BlKCk7CiAgICAgIHRocm93IGU7CiAgICB9CgogICAgaWYgKGlzVGhlbmFibGUobWF5YmVQcm9taXNlUmVzdWx0KSkgewogICAgICAvLyBAdHMtZXhwZWN0LWVycm9yIC0gaXNUaGVuYWJsZSByZXR1cm5zIHRoZSB3cm9uZyB0eXBlCiAgICAgIHJldHVybiBtYXliZVByb21pc2VSZXN1bHQudGhlbigKICAgICAgICByZXMgPT4gewogICAgICAgICAgdGhpcy5fcG9wU2NvcGUoKTsKICAgICAgICAgIHJldHVybiByZXM7CiAgICAgICAgfSwKICAgICAgICBlID0+IHsKICAgICAgICAgIHRoaXMuX3BvcFNjb3BlKCk7CiAgICAgICAgICB0aHJvdyBlOwogICAgICAgIH0sCiAgICAgICk7CiAgICB9CgogICAgdGhpcy5fcG9wU2NvcGUoKTsKICAgIHJldHVybiBtYXliZVByb21pc2VSZXN1bHQ7CiAgfQoKICAvKioKICAgKiBAaW5oZXJpdERvYwogICAqCiAgICogQGRlcHJlY2F0ZWQgVXNlIGBTZW50cnkuZ2V0Q2xpZW50KClgIGluc3RlYWQuCiAgICovCiAgIGdldENsaWVudCgpIHsKICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBkZXByZWNhdGlvbi9kZXByZWNhdGlvbgogICAgcmV0dXJuIHRoaXMuZ2V0U3RhY2tUb3AoKS5jbGllbnQgOwogIH0KCiAgLyoqCiAgICogUmV0dXJucyB0aGUgc2NvcGUgb2YgdGhlIHRvcCBzdGFjay4KICAgKgogICAqIEBkZXByZWNhdGVkIFVzZSBgU2VudHJ5LmdldEN1cnJlbnRTY29wZSgpYCBpbnN0ZWFkLgogICAqLwogICBnZXRTY29wZSgpIHsKICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBkZXByZWNhdGlvbi9kZXByZWNhdGlvbgogICAgcmV0dXJuIHRoaXMuZ2V0U3RhY2tUb3AoKS5zY29wZTsKICB9CgogIC8qKgogICAqIEBkZXByZWNhdGVkIFVzZSBgU2VudHJ5LmdldElzb2xhdGlvblNjb3BlKClgIGluc3RlYWQuCiAgICovCiAgIGdldElzb2xhdGlvblNjb3BlKCkgewogICAgcmV0dXJuIHRoaXMuX2lzb2xhdGlvblNjb3BlOwogIH0KCiAgLyoqCiAgICogUmV0dXJucyB0aGUgc2NvcGUgc3RhY2sgZm9yIGRvbWFpbnMgb3IgdGhlIHByb2Nlc3MuCiAgICogQGRlcHJlY2F0ZWQgVGhpcyB3aWxsIGJlIHJlbW92ZWQgaW4gdjguCiAgICovCiAgIGdldFN0YWNrKCkgewogICAgcmV0dXJuIHRoaXMuX3N0YWNrOwogIH0KCiAgLyoqCiAgICogUmV0dXJucyB0aGUgdG9wbW9zdCBzY29wZSBsYXllciBpbiB0aGUgb3JkZXIgZG9tYWluID4gbG9jYWwgPiBwcm9jZXNzLgogICAqIEBkZXByZWNhdGVkIFRoaXMgd2lsbCBiZSByZW1vdmVkIGluIHY4LgogICAqLwogICBnZXRTdGFja1RvcCgpIHsKICAgIHJldHVybiB0aGlzLl9zdGFja1t0aGlzLl9zdGFjay5sZW5ndGggLSAxXTsKICB9CgogIC8qKgogICAqIEBpbmhlcml0RG9jCiAgICoKICAgKiBAZGVwcmVjYXRlZCBVc2UgYFNlbnRyeS5jYXB0dXJlRXhjZXB0aW9uKClgIGluc3RlYWQuCiAgICovCiAgIGNhcHR1cmVFeGNlcHRpb24oZXhjZXB0aW9uLCBoaW50KSB7CiAgICBjb25zdCBldmVudElkID0gaGludCAmJiBoaW50LmV2ZW50X2lkID8gaGludC5ldmVudF9pZCA6IHV1aWQ0KCk7CiAgICBjb25zdCBzeW50aGV0aWNFeGNlcHRpb24gPSBuZXcgRXJyb3IoJ1NlbnRyeSBzeW50aGV0aWNFeGNlcHRpb24nKTsKICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBkZXByZWNhdGlvbi9kZXByZWNhdGlvbgogICAgdGhpcy5nZXRTY29wZSgpLmNhcHR1cmVFeGNlcHRpb24oZXhjZXB0aW9uLCB7CiAgICAgIG9yaWdpbmFsRXhjZXB0aW9uOiBleGNlcHRpb24sCiAgICAgIHN5bnRoZXRpY0V4Y2VwdGlvbiwKICAgICAgLi4uaGludCwKICAgICAgZXZlbnRfaWQ6IGV2ZW50SWQsCiAgICB9KTsKCiAgICByZXR1cm4gZXZlbnRJZDsKICB9CgogIC8qKgogICAqIEBpbmhlcml0RG9jCiAgICoKICAgKiBAZGVwcmVjYXRlZCBVc2UgIGBTZW50cnkuY2FwdHVyZU1lc3NhZ2UoKWAgaW5zdGVhZC4KICAgKi8KICAgY2FwdHVyZU1lc3NhZ2UobWVzc2FnZSwgbGV2ZWwsIGhpbnQpIHsKICAgIGNvbnN0IGV2ZW50SWQgPSBoaW50ICYmIGhpbnQuZXZlbnRfaWQgPyBoaW50LmV2ZW50X2lkIDogdXVpZDQoKTsKICAgIGNvbnN0IHN5bnRoZXRpY0V4Y2VwdGlvbiA9IG5ldyBFcnJvcihtZXNzYWdlKTsKICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBkZXByZWNhdGlvbi9kZXByZWNhdGlvbgogICAgdGhpcy5nZXRTY29wZSgpLmNhcHR1cmVNZXNzYWdlKG1lc3NhZ2UsIGxldmVsLCB7CiAgICAgIG9yaWdpbmFsRXhjZXB0aW9uOiBtZXNzYWdlLAogICAgICBzeW50aGV0aWNFeGNlcHRpb24sCiAgICAgIC4uLmhpbnQsCiAgICAgIGV2ZW50X2lkOiBldmVudElkLAogICAgfSk7CgogICAgcmV0dXJuIGV2ZW50SWQ7CiAgfQoKICAvKioKICAgKiBAaW5oZXJpdERvYwogICAqCiAgICogQGRlcHJlY2F0ZWQgVXNlIGBTZW50cnkuY2FwdHVyZUV2ZW50KClgIGluc3RlYWQuCiAgICovCiAgIGNhcHR1cmVFdmVudChldmVudCwgaGludCkgewogICAgY29uc3QgZXZlbnRJZCA9IGhpbnQgJiYgaGludC5ldmVudF9pZCA/IGhpbnQuZXZlbnRfaWQgOiB1dWlkNCgpOwogICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGRlcHJlY2F0aW9uL2RlcHJlY2F0aW9uCiAgICB0aGlzLmdldFNjb3BlKCkuY2FwdHVyZUV2ZW50KGV2ZW50LCB7IC4uLmhpbnQsIGV2ZW50X2lkOiBldmVudElkIH0pOwogICAgcmV0dXJuIGV2ZW50SWQ7CiAgfQoKICAvKioKICAgKiBAaW5oZXJpdERvYwogICAqCiAgICogQGRlcHJlY2F0ZWQgVXNlIGBTZW50cnkuYWRkQnJlYWRjcnVtYigpYCBpbnN0ZWFkLgogICAqLwogICBhZGRCcmVhZGNydW1iKGJyZWFkY3J1bWIsIGhpbnQpIHsKICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBkZXByZWNhdGlvbi9kZXByZWNhdGlvbgogICAgY29uc3QgeyBjbGllbnQgfSA9IHRoaXMuZ2V0U3RhY2tUb3AoKTsKCiAgICBpZiAoIWNsaWVudCkgcmV0dXJuOwoKICAgIGNvbnN0IHsgYmVmb3JlQnJlYWRjcnVtYiA9IG51bGwsIG1heEJyZWFkY3J1bWJzID0gREVGQVVMVF9CUkVBRENSVU1CUyB9ID0KICAgICAgKGNsaWVudC5nZXRPcHRpb25zICYmIGNsaWVudC5nZXRPcHRpb25zKCkpIHx8IHt9OwoKICAgIGlmIChtYXhCcmVhZGNydW1icyA8PSAwKSByZXR1cm47CgogICAgY29uc3QgdGltZXN0YW1wID0gZGF0ZVRpbWVzdGFtcEluU2Vjb25kcygpOwogICAgY29uc3QgbWVyZ2VkQnJlYWRjcnVtYiA9IHsgdGltZXN0YW1wLCAuLi5icmVhZGNydW1iIH07CiAgICBjb25zdCBmaW5hbEJyZWFkY3J1bWIgPSBiZWZvcmVCcmVhZGNydW1iCiAgICAgID8gKGNvbnNvbGVTYW5kYm94KCgpID0+IGJlZm9yZUJyZWFkY3J1bWIobWVyZ2VkQnJlYWRjcnVtYiwgaGludCkpICkKICAgICAgOiBtZXJnZWRCcmVhZGNydW1iOwoKICAgIGlmIChmaW5hbEJyZWFkY3J1bWIgPT09IG51bGwpIHJldHVybjsKCiAgICBjbGllbnQuZW1pdCgnYmVmb3JlQWRkQnJlYWRjcnVtYicsIGZpbmFsQnJlYWRjcnVtYiwgaGludCk7CgogICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGRlcHJlY2F0aW9uL2RlcHJlY2F0aW9uCiAgICB0aGlzLmdldElzb2xhdGlvblNjb3BlKCkuYWRkQnJlYWRjcnVtYihmaW5hbEJyZWFkY3J1bWIsIG1heEJyZWFkY3J1bWJzKTsKICB9CgogIC8qKgogICAqIEBpbmhlcml0RG9jCiAgICogQGRlcHJlY2F0ZWQgVXNlIGBTZW50cnkuc2V0VXNlcigpYCBpbnN0ZWFkLgogICAqLwogICBzZXRVc2VyKHVzZXIpIHsKICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBkZXByZWNhdGlvbi9kZXByZWNhdGlvbgogICAgdGhpcy5nZXRJc29sYXRpb25TY29wZSgpLnNldFVzZXIodXNlcik7CiAgfQoKICAvKioKICAgKiBAaW5oZXJpdERvYwogICAqIEBkZXByZWNhdGVkIFVzZSBgU2VudHJ5LnNldFRhZ3MoKWAgaW5zdGVhZC4KICAgKi8KICAgc2V0VGFncyh0YWdzKSB7CiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgZGVwcmVjYXRpb24vZGVwcmVjYXRpb24KICAgIHRoaXMuZ2V0SXNvbGF0aW9uU2NvcGUoKS5zZXRUYWdzKHRhZ3MpOwogIH0KCiAgLyoqCiAgICogQGluaGVyaXREb2MKICAgKiBAZGVwcmVjYXRlZCBVc2UgYFNlbnRyeS5zZXRFeHRyYXMoKWAgaW5zdGVhZC4KICAgKi8KICAgc2V0RXh0cmFzKGV4dHJhcykgewogICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGRlcHJlY2F0aW9uL2RlcHJlY2F0aW9uCiAgICB0aGlzLmdldElzb2xhdGlvblNjb3BlKCkuc2V0RXh0cmFzKGV4dHJhcyk7CiAgfQoKICAvKioKICAgKiBAaW5oZXJpdERvYwogICAqIEBkZXByZWNhdGVkIFVzZSBgU2VudHJ5LnNldFRhZygpYCBpbnN0ZWFkLgogICAqLwogICBzZXRUYWcoa2V5LCB2YWx1ZSkgewogICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGRlcHJlY2F0aW9uL2RlcHJlY2F0aW9uCiAgICB0aGlzLmdldElzb2xhdGlvblNjb3BlKCkuc2V0VGFnKGtleSwgdmFsdWUpOwogIH0KCiAgLyoqCiAgICogQGluaGVyaXREb2MKICAgKiBAZGVwcmVjYXRlZCBVc2UgYFNlbnRyeS5zZXRFeHRyYSgpYCBpbnN0ZWFkLgogICAqLwogICBzZXRFeHRyYShrZXksIGV4dHJhKSB7CiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgZGVwcmVjYXRpb24vZGVwcmVjYXRpb24KICAgIHRoaXMuZ2V0SXNvbGF0aW9uU2NvcGUoKS5zZXRFeHRyYShrZXksIGV4dHJhKTsKICB9CgogIC8qKgogICAqIEBpbmhlcml0RG9jCiAgICogQGRlcHJlY2F0ZWQgVXNlIGBTZW50cnkuc2V0Q29udGV4dCgpYCBpbnN0ZWFkLgogICAqLwogIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZXhwbGljaXQtYW55CiAgIHNldENvbnRleHQobmFtZSwgY29udGV4dCkgewogICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGRlcHJlY2F0aW9uL2RlcHJlY2F0aW9uCiAgICB0aGlzLmdldElzb2xhdGlvblNjb3BlKCkuc2V0Q29udGV4dChuYW1lLCBjb250ZXh0KTsKICB9CgogIC8qKgogICAqIEBpbmhlcml0RG9jCiAgICogQGRlcHJlY2F0ZWQgVXNlIGBTZW50cnkuZ2V0Q2xpZW50KCkuZ2V0SW50ZWdyYXRpb25CeU5hbWUoKWAgaW5zdGVhZC4KICAgKi8KICAgZ2V0SW50ZWdyYXRpb24oaW50ZWdyYXRpb24pIHsKICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBkZXByZWNhdGlvbi9kZXByZWNhdGlvbgogICAgY29uc3QgY2xpZW50ID0gdGhpcy5nZXRDbGllbnQoKTsKICAgIGlmICghY2xpZW50KSByZXR1cm4gbnVsbDsKICAgIHRyeSB7CiAgICAgIHJldHVybiBjbGllbnQuZ2V0SW50ZWdyYXRpb25CeU5hbWUoaW50ZWdyYXRpb24uaWQpIHx8IG51bGw7CiAgICB9IGNhdGNoIChfb08pIHsKICAgICAgREVCVUdfQlVJTEQgJiYgbG9nZ2VyLndhcm4oYENhbm5vdCByZXRyaWV2ZSBpbnRlZ3JhdGlvbiAke2ludGVncmF0aW9uLmlkfSBmcm9tIHRoZSBjdXJyZW50IEh1YmApOwogICAgICByZXR1cm4gbnVsbDsKICAgIH0KICB9CgogIC8qKgogICAqIEBpbmhlcml0RG9jCiAgICoKICAgKiBAZGVwcmVjYXRlZCBVc2UgdG9wIGxldmVsIGBjYXB0dXJlU2Vzc2lvbmAgaW5zdGVhZC4KICAgKi8KICAgY2FwdHVyZVNlc3Npb24oZW5kU2Vzc2lvbiA9IGZhbHNlKSB7CiAgICAvLyBib3RoIHNlbmQgdGhlIHVwZGF0ZSBhbmQgcHVsbCB0aGUgc2Vzc2lvbiBmcm9tIHRoZSBzY29wZQogICAgaWYgKGVuZFNlc3Npb24pIHsKICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGRlcHJlY2F0aW9uL2RlcHJlY2F0aW9uCiAgICAgIHJldHVybiB0aGlzLmVuZFNlc3Npb24oKTsKICAgIH0KCiAgICAvLyBvbmx5IHNlbmQgdGhlIHVwZGF0ZQogICAgdGhpcy5fc2VuZFNlc3Npb25VcGRhdGUoKTsKICB9CgogIC8qKgogICAqIEBpbmhlcml0RG9jCiAgICogQGRlcHJlY2F0ZWQgVXNlIHRvcCBsZXZlbCBgZW5kU2Vzc2lvbmAgaW5zdGVhZC4KICAgKi8KICAgZW5kU2Vzc2lvbigpIHsKICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBkZXByZWNhdGlvbi9kZXByZWNhdGlvbgogICAgY29uc3QgbGF5ZXIgPSB0aGlzLmdldFN0YWNrVG9wKCk7CiAgICBjb25zdCBzY29wZSA9IGxheWVyLnNjb3BlOwogICAgY29uc3Qgc2Vzc2lvbiA9IHNjb3BlLmdldFNlc3Npb24oKTsKICAgIGlmIChzZXNzaW9uKSB7CiAgICAgIGNsb3NlU2Vzc2lvbihzZXNzaW9uKTsKICAgIH0KICAgIHRoaXMuX3NlbmRTZXNzaW9uVXBkYXRlKCk7CgogICAgLy8gdGhlIHNlc3Npb24gaXMgb3ZlcjsgdGFrZSBpdCBvZmYgb2YgdGhlIHNjb3BlCiAgICBzY29wZS5zZXRTZXNzaW9uKCk7CiAgfQoKICAvKioKICAgKiBAaW5oZXJpdERvYwogICAqIEBkZXByZWNhdGVkIFVzZSB0b3AgbGV2ZWwgYHN0YXJ0U2Vzc2lvbmAgaW5zdGVhZC4KICAgKi8KICAgc3RhcnRTZXNzaW9uKGNvbnRleHQpIHsKICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBkZXByZWNhdGlvbi9kZXByZWNhdGlvbgogICAgY29uc3QgeyBzY29wZSwgY2xpZW50IH0gPSB0aGlzLmdldFN0YWNrVG9wKCk7CiAgICBjb25zdCB7IHJlbGVhc2UsIGVudmlyb25tZW50ID0gREVGQVVMVF9FTlZJUk9OTUVOVCB9ID0gKGNsaWVudCAmJiBjbGllbnQuZ2V0T3B0aW9ucygpKSB8fCB7fTsKCiAgICAvLyBXaWxsIGZldGNoIHVzZXJBZ2VudCBpZiBjYWxsZWQgZnJvbSBicm93c2VyIHNkawogICAgY29uc3QgeyB1c2VyQWdlbnQgfSA9IEdMT0JBTF9PQkoubmF2aWdhdG9yIHx8IHt9OwoKICAgIGNvbnN0IHNlc3Npb24gPSBtYWtlU2Vzc2lvbih7CiAgICAgIHJlbGVhc2UsCiAgICAgIGVudmlyb25tZW50LAogICAgICB1c2VyOiBzY29wZS5nZXRVc2VyKCksCiAgICAgIC4uLih1c2VyQWdlbnQgJiYgeyB1c2VyQWdlbnQgfSksCiAgICAgIC4uLmNvbnRleHQsCiAgICB9KTsKCiAgICAvLyBFbmQgZXhpc3Rpbmcgc2Vzc2lvbiBpZiB0aGVyZSdzIG9uZQogICAgY29uc3QgY3VycmVudFNlc3Npb24gPSBzY29wZS5nZXRTZXNzaW9uICYmIHNjb3BlLmdldFNlc3Npb24oKTsKICAgIGlmIChjdXJyZW50U2Vzc2lvbiAmJiBjdXJyZW50U2Vzc2lvbi5zdGF0dXMgPT09ICdvaycpIHsKICAgICAgdXBkYXRlU2Vzc2lvbihjdXJyZW50U2Vzc2lvbiwgeyBzdGF0dXM6ICdleGl0ZWQnIH0pOwogICAgfQogICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGRlcHJlY2F0aW9uL2RlcHJlY2F0aW9uCiAgICB0aGlzLmVuZFNlc3Npb24oKTsKCiAgICAvLyBBZnRlcndhcmRzIHdlIHNldCB0aGUgbmV3IHNlc3Npb24gb24gdGhlIHNjb3BlCiAgICBzY29wZS5zZXRTZXNzaW9uKHNlc3Npb24pOwoKICAgIHJldHVybiBzZXNzaW9uOwogIH0KCiAgLyoqCiAgICogU2VuZHMgdGhlIGN1cnJlbnQgU2Vzc2lvbiBvbiB0aGUgc2NvcGUKICAgKi8KICAgX3NlbmRTZXNzaW9uVXBkYXRlKCkgewogICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGRlcHJlY2F0aW9uL2RlcHJlY2F0aW9uCiAgICBjb25zdCB7IHNjb3BlLCBjbGllbnQgfSA9IHRoaXMuZ2V0U3RhY2tUb3AoKTsKCiAgICBjb25zdCBzZXNzaW9uID0gc2NvcGUuZ2V0U2Vzc2lvbigpOwogICAgaWYgKHNlc3Npb24gJiYgY2xpZW50ICYmIGNsaWVudC5jYXB0dXJlU2Vzc2lvbikgewogICAgICBjbGllbnQuY2FwdHVyZVNlc3Npb24oc2Vzc2lvbik7CiAgICB9CiAgfQoKICAvKioKICAgKiBQdXNoIGEgc2NvcGUgdG8gdGhlIHN0YWNrLgogICAqLwogICBfcHVzaFNjb3BlKCkgewogICAgLy8gV2Ugd2FudCB0byBjbG9uZSB0aGUgY29udGVudCBvZiBwcmV2IHNjb3BlCiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgZGVwcmVjYXRpb24vZGVwcmVjYXRpb24KICAgIGNvbnN0IHNjb3BlID0gdGhpcy5nZXRTY29wZSgpLmNsb25lKCk7CiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgZGVwcmVjYXRpb24vZGVwcmVjYXRpb24KICAgIHRoaXMuZ2V0U3RhY2soKS5wdXNoKHsKICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGRlcHJlY2F0aW9uL2RlcHJlY2F0aW9uCiAgICAgIGNsaWVudDogdGhpcy5nZXRDbGllbnQoKSwKICAgICAgc2NvcGUsCiAgICB9KTsKICAgIHJldHVybiBzY29wZTsKICB9CgogIC8qKgogICAqIFBvcCBhIHNjb3BlIGZyb20gdGhlIHN0YWNrLgogICAqLwogICBfcG9wU2NvcGUoKSB7CiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgZGVwcmVjYXRpb24vZGVwcmVjYXRpb24KICAgIGlmICh0aGlzLmdldFN0YWNrKCkubGVuZ3RoIDw9IDEpIHJldHVybiBmYWxzZTsKICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBkZXByZWNhdGlvbi9kZXByZWNhdGlvbgogICAgcmV0dXJuICEhdGhpcy5nZXRTdGFjaygpLnBvcCgpOwogIH0KfQoKLyoqIEdldCB0aGUgZGVmYXVsdCBjdXJyZW50IHNjb3BlLiAqLwpmdW5jdGlvbiBnZXREZWZhdWx0Q3VycmVudFNjb3BlKCkgewogIHJldHVybiBnZXRHbG9iYWxTaW5nbGV0b24oJ2RlZmF1bHRDdXJyZW50U2NvcGUnLCAoKSA9PiBuZXcgU2NvcGUoKSk7Cn0KCi8qKiBHZXQgdGhlIGRlZmF1bHQgaXNvbGF0aW9uIHNjb3BlLiAqLwpmdW5jdGlvbiBnZXREZWZhdWx0SXNvbGF0aW9uU2NvcGUoKSB7CiAgcmV0dXJuIGdldEdsb2JhbFNpbmdsZXRvbignZGVmYXVsdElzb2xhdGlvblNjb3BlJywgKCkgPT4gbmV3IFNjb3BlKCkpOwp9CgovKioKICogR2V0IHRoZSBnbG9iYWwgaHViLgogKiBUaGlzIHdpbGwgYmUgcmVtb3ZlZCBkdXJpbmcgdGhlIHY4IGN5Y2xlIGFuZCBpcyBvbmx5IGhlcmUgdG8gbWFrZSBtaWdyYXRpb24gZWFzaWVyLgogKi8KLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGRlcHJlY2F0aW9uL2RlcHJlY2F0aW9uCmZ1bmN0aW9uIGdldEdsb2JhbEh1YigpIHsKICBjb25zdCByZWdpc3RyeSA9IGdldE1haW5DYXJyaWVyKCk7CiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGRlcHJlY2F0aW9uL2RlcHJlY2F0aW9uCiAgY29uc3Qgc2VudHJ5ID0gZ2V0U2VudHJ5Q2FycmllcihyZWdpc3RyeSkgOwoKICAvLyBJZiB0aGVyZSdzIG5vIGh1Yiwgb3IgaXRzIGFuIG9sZCBBUEksIGFzc2lnbiBhIG5ldyBvbmUKICBpZiAoc2VudHJ5Lmh1YikgewogICAgcmV0dXJuIHNlbnRyeS5odWI7CiAgfQoKICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgZGVwcmVjYXRpb24vZGVwcmVjYXRpb24KICBzZW50cnkuaHViID0gbmV3IEh1Yih1bmRlZmluZWQsIGdldERlZmF1bHRDdXJyZW50U2NvcGUoKSwgZ2V0RGVmYXVsdElzb2xhdGlvblNjb3BlKCkpOwogIHJldHVybiBzZW50cnkuaHViOwp9CgovKioKICogR2V0IHRoZSBjdXJyZW50IGFzeW5jIGNvbnRleHQgc3RyYXRlZ3kuCiAqIElmIG5vbmUgaGFzIGJlZW4gc2V0dXAsIHRoZSBkZWZhdWx0IHdpbGwgYmUgdXNlZC4KICovCmZ1bmN0aW9uIGdldEFzeW5jQ29udGV4dFN0cmF0ZWd5KGNhcnJpZXIpIHsKICBjb25zdCBzZW50cnkgPSBnZXRTZW50cnlDYXJyaWVyKGNhcnJpZXIpOwoKICBpZiAoc2VudHJ5LmFjcykgewogICAgcmV0dXJuIHNlbnRyeS5hY3M7CiAgfQoKICAvLyBPdGhlcndpc2UsIHVzZSB0aGUgZGVmYXVsdCBvbmUKICByZXR1cm4gZ2V0SHViU3RhY2tBc3luY0NvbnRleHRTdHJhdGVneSgpOwp9CgpmdW5jdGlvbiB3aXRoU2NvcGUkMShjYWxsYmFjaykgewogIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBkZXByZWNhdGlvbi9kZXByZWNhdGlvbgogIHJldHVybiBnZXRHbG9iYWxIdWIoKS53aXRoU2NvcGUoY2FsbGJhY2spOwp9CgpmdW5jdGlvbiB3aXRoU2V0U2NvcGUoc2NvcGUsIGNhbGxiYWNrKSB7CiAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGRlcHJlY2F0aW9uL2RlcHJlY2F0aW9uCiAgY29uc3QgaHViID0gZ2V0R2xvYmFsSHViKCkgOwogIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBkZXByZWNhdGlvbi9kZXByZWNhdGlvbgogIHJldHVybiBodWIud2l0aFNjb3BlKCgpID0+IHsKICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBkZXByZWNhdGlvbi9kZXByZWNhdGlvbgogICAgaHViLmdldFN0YWNrVG9wKCkuc2NvcGUgPSBzY29wZSA7CiAgICByZXR1cm4gY2FsbGJhY2soc2NvcGUpOwogIH0pOwp9CgpmdW5jdGlvbiB3aXRoSXNvbGF0aW9uU2NvcGUoY2FsbGJhY2spIHsKICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgZGVwcmVjYXRpb24vZGVwcmVjYXRpb24KICByZXR1cm4gZ2V0R2xvYmFsSHViKCkud2l0aFNjb3BlKCgpID0+IHsKICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBkZXByZWNhdGlvbi9kZXByZWNhdGlvbgogICAgcmV0dXJuIGNhbGxiYWNrKGdldEdsb2JhbEh1YigpLmdldElzb2xhdGlvblNjb3BlKCkpOwogIH0pOwp9CgovKiBlc2xpbnQtZGlzYWJsZSBkZXByZWNhdGlvbi9kZXByZWNhdGlvbiAqLwpmdW5jdGlvbiBnZXRIdWJTdGFja0FzeW5jQ29udGV4dFN0cmF0ZWd5KCkgewogIHJldHVybiB7CiAgICB3aXRoSXNvbGF0aW9uU2NvcGUsCiAgICB3aXRoU2NvcGU6IHdpdGhTY29wZSQxLAogICAgd2l0aFNldFNjb3BlLAogICAgd2l0aFNldElzb2xhdGlvblNjb3BlOiAoX2lzb2xhdGlvblNjb3BlLCBjYWxsYmFjaykgPT4gewogICAgICByZXR1cm4gd2l0aElzb2xhdGlvblNjb3BlKGNhbGxiYWNrKTsKICAgIH0sCiAgICBnZXRDdXJyZW50U2NvcGU6ICgpID0+IGdldEdsb2JhbEh1YigpLmdldFNjb3BlKCksCiAgICBnZXRJc29sYXRpb25TY29wZTogKCkgPT4gZ2V0R2xvYmFsSHViKCkuZ2V0SXNvbGF0aW9uU2NvcGUoKSwKICB9Owp9CgovKioKICogR2V0IHRoZSBjdXJyZW50bHkgYWN0aXZlIHNjb3BlLgogKi8KZnVuY3Rpb24gZ2V0Q3VycmVudFNjb3BlKCkgewogIGNvbnN0IGNhcnJpZXIgPSBnZXRNYWluQ2FycmllcigpOwogIGNvbnN0IGFjcyA9IGdldEFzeW5jQ29udGV4dFN0cmF0ZWd5KGNhcnJpZXIpOwogIHJldHVybiBhY3MuZ2V0Q3VycmVudFNjb3BlKCk7Cn0KCi8qKgogKiBDcmVhdGVzIGEgbmV3IHNjb3BlIHdpdGggYW5kIGV4ZWN1dGVzIHRoZSBnaXZlbiBvcGVyYXRpb24gd2l0aGluLgogKiBUaGUgc2NvcGUgaXMgYXV0b21hdGljYWxseSByZW1vdmVkIG9uY2UgdGhlIG9wZXJhdGlvbgogKiBmaW5pc2hlcyBvciB0aHJvd3MuCiAqLwoKLyoqCiAqIEVpdGhlciBjcmVhdGVzIGEgbmV3IGFjdGl2ZSBzY29wZSwgb3Igc2V0cyB0aGUgZ2l2ZW4gc2NvcGUgYXMgYWN0aXZlIHNjb3BlIGluIHRoZSBnaXZlbiBjYWxsYmFjay4KICovCmZ1bmN0aW9uIHdpdGhTY29wZSgKICAuLi5yZXN0CikgewogIGNvbnN0IGNhcnJpZXIgPSBnZXRNYWluQ2FycmllcigpOwogIGNvbnN0IGFjcyA9IGdldEFzeW5jQ29udGV4dFN0cmF0ZWd5KGNhcnJpZXIpOwoKICAvLyBJZiBhIHNjb3BlIGlzIGRlZmluZWQsIHdlIHdhbnQgdG8gbWFrZSB0aGlzIHRoZSBhY3RpdmUgc2NvcGUgaW5zdGVhZCBvZiB0aGUgZGVmYXVsdCBvbmUKICBpZiAocmVzdC5sZW5ndGggPT09IDIpIHsKICAgIGNvbnN0IFtzY29wZSwgY2FsbGJhY2tdID0gcmVzdDsKCiAgICBpZiAoIXNjb3BlKSB7CiAgICAgIHJldHVybiBhY3Mud2l0aFNjb3BlKGNhbGxiYWNrKTsKICAgIH0KCiAgICByZXR1cm4gYWNzLndpdGhTZXRTY29wZShzY29wZSwgY2FsbGJhY2spOwogIH0KCiAgcmV0dXJuIGFjcy53aXRoU2NvcGUocmVzdFswXSk7Cn0KCi8qKgogKiBHZXQgdGhlIGN1cnJlbnRseSBhY3RpdmUgY2xpZW50LgogKi8KZnVuY3Rpb24gZ2V0Q2xpZW50KCkgewogIHJldHVybiBnZXRDdXJyZW50U2NvcGUoKS5nZXRDbGllbnQoKTsKfQoKLyoqCiAqIEZldGNoZXMgdGhlIG1ldHJpYyBzdW1tYXJ5IGlmIGl0IGV4aXN0cyBmb3IgdGhlIHBhc3NlZCBzcGFuCiAqLwpmdW5jdGlvbiBnZXRNZXRyaWNTdW1tYXJ5SnNvbkZvclNwYW4oc3BhbikgewoKICB7CiAgICByZXR1cm4gdW5kZWZpbmVkOwogIH0KfQoKLyoqCiAqIFVzZSB0aGlzIGF0dHJpYnV0ZSB0byByZXByZXNlbnQgdGhlIHNvdXJjZSBvZiBhIHNwYW4uCiAqIFNob3VsZCBiZSBvbmUgb2Y6IGN1c3RvbSwgdXJsLCByb3V0ZSwgdmlldywgY29tcG9uZW50LCB0YXNrLCB1bmtub3duCiAqCiAqLwpjb25zdCBTRU1BTlRJQ19BVFRSSUJVVEVfU0VOVFJZX1NPVVJDRSA9ICdzZW50cnkuc291cmNlJzsKCi8qKgogKiBVc2UgdGhpcyBhdHRyaWJ1dGUgdG8gcmVwcmVzZW50IHRoZSBzYW1wbGUgcmF0ZSB1c2VkIGZvciBhIHNwYW4uCiAqLwpjb25zdCBTRU1BTlRJQ19BVFRSSUJVVEVfU0VOVFJZX1NBTVBMRV9SQVRFID0gJ3NlbnRyeS5zYW1wbGVfcmF0ZSc7CgovKioKICogVXNlIHRoaXMgYXR0cmlidXRlIHRvIHJlcHJlc2VudCB0aGUgb3BlcmF0aW9uIG9mIGEgc3Bhbi4KICovCmNvbnN0IFNFTUFOVElDX0FUVFJJQlVURV9TRU5UUllfT1AgPSAnc2VudHJ5Lm9wJzsKCi8qKgogKiBVc2UgdGhpcyBhdHRyaWJ1dGUgdG8gcmVwcmVzZW50IHRoZSBvcmlnaW4gb2YgYSBzcGFuLgogKi8KY29uc3QgU0VNQU5USUNfQVRUUklCVVRFX1NFTlRSWV9PUklHSU4gPSAnc2VudHJ5Lm9yaWdpbic7Cgpjb25zdCBTUEFOX1NUQVRVU19VTlNFVCA9IDA7CmNvbnN0IFNQQU5fU1RBVFVTX09LID0gMTsKCmNvbnN0IFRSQUNFX0ZMQUdfU0FNUExFRCA9IDB4MTsKCi8qKgogKiBDb252ZXJ0IGEgc3BhbiB0byBhIHRyYWNlIGNvbnRleHQsIHdoaWNoIGNhbiBiZSBzZW50IGFzIHRoZSBgdHJhY2VgIGNvbnRleHQgaW4gYW4gZXZlbnQuCiAqLwpmdW5jdGlvbiBzcGFuVG9UcmFjZUNvbnRleHQoc3BhbikgewogIGNvbnN0IHsgc3BhbklkOiBzcGFuX2lkLCB0cmFjZUlkOiB0cmFjZV9pZCB9ID0gc3Bhbi5zcGFuQ29udGV4dCgpOwogIGNvbnN0IHsgZGF0YSwgb3AsIHBhcmVudF9zcGFuX2lkLCBzdGF0dXMsIG9yaWdpbiB9ID0gc3BhblRvSlNPTihzcGFuKTsKCiAgcmV0dXJuIGRyb3BVbmRlZmluZWRLZXlzKHsKICAgIGRhdGEsCiAgICBvcCwKICAgIHBhcmVudF9zcGFuX2lkLAogICAgc3Bhbl9pZCwKICAgIHN0YXR1cywKICAgIHRyYWNlX2lkLAogICAgb3JpZ2luLAogIH0pOwp9CgovKioKICogQ29udmVydCBhIHNwYW4gdGltZSBpbnB1dCBpbnRwIGEgdGltZXN0YW1wIGluIHNlY29uZHMuCiAqLwpmdW5jdGlvbiBzcGFuVGltZUlucHV0VG9TZWNvbmRzKGlucHV0KSB7CiAgaWYgKHR5cGVvZiBpbnB1dCA9PT0gJ251bWJlcicpIHsKICAgIHJldHVybiBlbnN1cmVUaW1lc3RhbXBJblNlY29uZHMoaW5wdXQpOwogIH0KCiAgaWYgKEFycmF5LmlzQXJyYXkoaW5wdXQpKSB7CiAgICAvLyBTZWUge0BsaW5rIEhyVGltZX0gZm9yIHRoZSBhcnJheS1iYXNlZCB0aW1lIGZvcm1hdAogICAgcmV0dXJuIGlucHV0WzBdICsgaW5wdXRbMV0gLyAxZTk7CiAgfQoKICBpZiAoaW5wdXQgaW5zdGFuY2VvZiBEYXRlKSB7CiAgICByZXR1cm4gZW5zdXJlVGltZXN0YW1wSW5TZWNvbmRzKGlucHV0LmdldFRpbWUoKSk7CiAgfQoKICByZXR1cm4gdGltZXN0YW1wSW5TZWNvbmRzKCk7Cn0KCi8qKgogKiBDb252ZXJ0cyBhIHRpbWVzdGFtcCB0byBzZWNvbmQsIGlmIGl0IHdhcyBpbiBtaWxsaXNlY29uZHMsIG9yIGtlZXBzIGl0IGFzIHNlY29uZC4KICovCmZ1bmN0aW9uIGVuc3VyZVRpbWVzdGFtcEluU2Vjb25kcyh0aW1lc3RhbXApIHsKICBjb25zdCBpc01zID0gdGltZXN0YW1wID4gOTk5OTk5OTk5OTsKICByZXR1cm4gaXNNcyA/IHRpbWVzdGFtcCAvIDEwMDAgOiB0aW1lc3RhbXA7Cn0KCi8qKgogKiBDb252ZXJ0IGEgc3BhbiB0byBhIEpTT04gcmVwcmVzZW50YXRpb24uCiAqLwovLyBOb3RlOiBCZWNhdXNlIG9mIHRoaXMsIHdlIGN1cnJlbnRseSBoYXZlIGEgY2lyY3VsYXIgdHlwZSBkZXBlbmRlbmN5ICh3aGljaCB3ZSBvcHRlZCBvdXQgb2YgaW4gcGFja2FnZS5qc29uKS4KLy8gVGhpcyBpcyBub3QgYXZvaWRhYmxlIGFzIHdlIG5lZWQgYHNwYW5Ub0pTT05gIGluIGBzcGFuVXRpbHMudHNgLCB3aGljaCBpbiB0dXJuIGlzIG5lZWRlZCBieSBgc3Bhbi50c2AgZm9yIGJhY2t3YXJkcyBjb21wYXRpYmlsaXR5LgovLyBBbmQgYHNwYW5Ub0pTT05gIG5lZWRzIHRoZSBTcGFuIGNsYXNzIGZyb20gYHNwYW4udHNgIHRvIGNoZWNrIGhlcmUuCmZ1bmN0aW9uIHNwYW5Ub0pTT04oc3BhbikgewogIGlmIChzcGFuSXNTZW50cnlTcGFuKHNwYW4pKSB7CiAgICByZXR1cm4gc3Bhbi5nZXRTcGFuSlNPTigpOwogIH0KCiAgdHJ5IHsKICAgIGNvbnN0IHsgc3BhbklkOiBzcGFuX2lkLCB0cmFjZUlkOiB0cmFjZV9pZCB9ID0gc3Bhbi5zcGFuQ29udGV4dCgpOwoKICAgIC8vIEhhbmRsZSBhIHNwYW4gZnJvbSBAb3BlbnRlbGVtZXRyeS9zZGstYmFzZS10cmFjZSdzIGBTcGFuYCBjbGFzcwogICAgaWYgKHNwYW5Jc09wZW5UZWxlbWV0cnlTZGtUcmFjZUJhc2VTcGFuKHNwYW4pKSB7CiAgICAgIGNvbnN0IHsgYXR0cmlidXRlcywgc3RhcnRUaW1lLCBuYW1lLCBlbmRUaW1lLCBwYXJlbnRTcGFuSWQsIHN0YXR1cyB9ID0gc3BhbjsKCiAgICAgIHJldHVybiBkcm9wVW5kZWZpbmVkS2V5cyh7CiAgICAgICAgc3Bhbl9pZCwKICAgICAgICB0cmFjZV9pZCwKICAgICAgICBkYXRhOiBhdHRyaWJ1dGVzLAogICAgICAgIGRlc2NyaXB0aW9uOiBuYW1lLAogICAgICAgIHBhcmVudF9zcGFuX2lkOiBwYXJlbnRTcGFuSWQsCiAgICAgICAgc3RhcnRfdGltZXN0YW1wOiBzcGFuVGltZUlucHV0VG9TZWNvbmRzKHN0YXJ0VGltZSksCiAgICAgICAgLy8gVGhpcyBpcyBbMCwwXSBieSBkZWZhdWx0IGluIE9URUwsIGluIHdoaWNoIGNhc2Ugd2Ugd2FudCB0byBpbnRlcnByZXQgdGhpcyBhcyBubyBlbmQgdGltZQogICAgICAgIHRpbWVzdGFtcDogc3BhblRpbWVJbnB1dFRvU2Vjb25kcyhlbmRUaW1lKSB8fCB1bmRlZmluZWQsCiAgICAgICAgc3RhdHVzOiBnZXRTdGF0dXNNZXNzYWdlKHN0YXR1cyksCiAgICAgICAgb3A6IGF0dHJpYnV0ZXNbU0VNQU5USUNfQVRUUklCVVRFX1NFTlRSWV9PUF0sCiAgICAgICAgb3JpZ2luOiBhdHRyaWJ1dGVzW1NFTUFOVElDX0FUVFJJQlVURV9TRU5UUllfT1JJR0lOXSAsCiAgICAgICAgX21ldHJpY3Nfc3VtbWFyeTogZ2V0TWV0cmljU3VtbWFyeUpzb25Gb3JTcGFuKCksCiAgICAgIH0pOwogICAgfQoKICAgIC8vIEZpbmFsbHksIGF0IGxlYXN0IHdlIGhhdmUgYHNwYW5Db250ZXh0KClgLi4uLgogICAgcmV0dXJuIHsKICAgICAgc3Bhbl9pZCwKICAgICAgdHJhY2VfaWQsCiAgICB9OwogIH0gY2F0Y2ggKGUpIHsKICAgIHJldHVybiB7fTsKICB9Cn0KCmZ1bmN0aW9uIHNwYW5Jc09wZW5UZWxlbWV0cnlTZGtUcmFjZUJhc2VTcGFuKHNwYW4pIHsKICBjb25zdCBjYXN0U3BhbiA9IHNwYW4gOwogIHJldHVybiAhIWNhc3RTcGFuLmF0dHJpYnV0ZXMgJiYgISFjYXN0U3Bhbi5zdGFydFRpbWUgJiYgISFjYXN0U3Bhbi5uYW1lICYmICEhY2FzdFNwYW4uZW5kVGltZSAmJiAhIWNhc3RTcGFuLnN0YXR1czsKfQoKLyoqIEV4cG9ydGVkIG9ubHkgZm9yIHRlc3RzLiAqLwoKLyoqCiAqIFNhZGx5LCBkdWUgdG8gY2lyY3VsYXIgZGVwZW5kZW5jeSBjaGVja3Mgd2UgY2Fubm90IGFjdHVhbGx5IGltcG9ydCB0aGUgU3BhbiBjbGFzcyBoZXJlIGFuZCBjaGVjayBmb3IgaW5zdGFuY2VvZi4KICogOiggU28gaW5zdGVhZCB3ZSBhcHByb3hpbWF0ZSB0aGlzIGJ5IGNoZWNraW5nIGlmIGl0IGhhcyB0aGUgYGdldFNwYW5KU09OYCBtZXRob2QuCiAqLwpmdW5jdGlvbiBzcGFuSXNTZW50cnlTcGFuKHNwYW4pIHsKICByZXR1cm4gdHlwZW9mIChzcGFuICkuZ2V0U3BhbkpTT04gPT09ICdmdW5jdGlvbic7Cn0KCi8qKgogKiBSZXR1cm5zIHRydWUgaWYgYSBzcGFuIGlzIHNhbXBsZWQuCiAqIEluIG1vc3QgY2FzZXMsIHlvdSBzaG91bGQganVzdCB1c2UgYHNwYW4uaXNSZWNvcmRpbmcoKWAgaW5zdGVhZC4KICogSG93ZXZlciwgdGhpcyBoYXMgYSBzbGlnaHRseSBkaWZmZXJlbnQgc2VtYW50aWMsIGFzIGl0IGFsc28gcmV0dXJucyBmYWxzZSBpZiB0aGUgc3BhbiBpcyBmaW5pc2hlZC4KICogU28gaW4gdGhlIGNhc2Ugd2hlcmUgdGhpcyBkaXN0aW5jdGlvbiBpcyBpbXBvcnRhbnQsIHVzZSB0aGlzIG1ldGhvZC4KICovCmZ1bmN0aW9uIHNwYW5Jc1NhbXBsZWQoc3BhbikgewogIC8vIFdlIGFsaWduIG91ciB0cmFjZSBmbGFncyB3aXRoIHRoZSBvbmVzIE9wZW5UZWxlbWV0cnkgdXNlCiAgLy8gU28gd2UgYWxzbyBjaGVjayBmb3Igc2FtcGxlZCB0aGUgc2FtZSB3YXkgdGhleSBkby4KICBjb25zdCB7IHRyYWNlRmxhZ3MgfSA9IHNwYW4uc3BhbkNvbnRleHQoKTsKICByZXR1cm4gdHJhY2VGbGFncyA9PT0gVFJBQ0VfRkxBR19TQU1QTEVEOwp9CgovKiogR2V0IHRoZSBzdGF0dXMgbWVzc2FnZSB0byB1c2UgZm9yIGEgSlNPTiByZXByZXNlbnRhdGlvbiBvZiBhIHNwYW4uICovCmZ1bmN0aW9uIGdldFN0YXR1c01lc3NhZ2Uoc3RhdHVzKSB7CiAgaWYgKCFzdGF0dXMgfHwgc3RhdHVzLmNvZGUgPT09IFNQQU5fU1RBVFVTX1VOU0VUKSB7CiAgICByZXR1cm4gdW5kZWZpbmVkOwogIH0KCiAgaWYgKHN0YXR1cy5jb2RlID09PSBTUEFOX1NUQVRVU19PSykgewogICAgcmV0dXJuICdvayc7CiAgfQoKICByZXR1cm4gc3RhdHVzLm1lc3NhZ2UgfHwgJ3Vua25vd25fZXJyb3InOwp9CmNvbnN0IFJPT1RfU1BBTl9GSUVMRCA9ICdfc2VudHJ5Um9vdFNwYW4nOwoKLyoqCiAqIFJldHVybnMgdGhlIHJvb3Qgc3BhbiBvZiBhIGdpdmVuIHNwYW4uCiAqLwpmdW5jdGlvbiBnZXRSb290U3BhbihzcGFuKSB7CiAgcmV0dXJuIHNwYW5bUk9PVF9TUEFOX0ZJRUxEXSB8fCBzcGFuOwp9CgovKioKICogSWYgeW91IGNoYW5nZSB0aGlzIHZhbHVlLCBhbHNvIHVwZGF0ZSB0aGUgdGVyc2VyIHBsdWdpbiBjb25maWcgdG8KICogYXZvaWQgbWluaWZpY2F0aW9uIG9mIHRoZSBvYmplY3QgcHJvcGVydHkhCiAqLwpjb25zdCBGUk9aRU5fRFNDX0ZJRUxEID0gJ19mcm96ZW5Ec2MnOwoKLyoqCiAqIENyZWF0ZXMgYSBkeW5hbWljIHNhbXBsaW5nIGNvbnRleHQgZnJvbSBhIGNsaWVudC4KICoKICogRGlzcGF0Y2hlcyB0aGUgYGNyZWF0ZURzY2AgbGlmZWN5Y2xlIGhvb2sgYXMgYSBzaWRlIGVmZmVjdC4KICovCmZ1bmN0aW9uIGdldER5bmFtaWNTYW1wbGluZ0NvbnRleHRGcm9tQ2xpZW50KHRyYWNlX2lkLCBjbGllbnQpIHsKICBjb25zdCBvcHRpb25zID0gY2xpZW50LmdldE9wdGlvbnMoKTsKCiAgY29uc3QgeyBwdWJsaWNLZXk6IHB1YmxpY19rZXkgfSA9IGNsaWVudC5nZXREc24oKSB8fCB7fTsKCiAgY29uc3QgZHNjID0gZHJvcFVuZGVmaW5lZEtleXMoewogICAgZW52aXJvbm1lbnQ6IG9wdGlvbnMuZW52aXJvbm1lbnQgfHwgREVGQVVMVF9FTlZJUk9OTUVOVCwKICAgIHJlbGVhc2U6IG9wdGlvbnMucmVsZWFzZSwKICAgIHB1YmxpY19rZXksCiAgICB0cmFjZV9pZCwKICB9KSA7CgogIGNsaWVudC5lbWl0KCdjcmVhdGVEc2MnLCBkc2MpOwoKICByZXR1cm4gZHNjOwp9CgovKioKICogQ3JlYXRlcyBhIGR5bmFtaWMgc2FtcGxpbmcgY29udGV4dCBmcm9tIGEgc3BhbiAoYW5kIGNsaWVudCBhbmQgc2NvcGUpCiAqCiAqIEBwYXJhbSBzcGFuIHRoZSBzcGFuIGZyb20gd2hpY2ggYSBmZXcgdmFsdWVzIGxpa2UgdGhlIHJvb3Qgc3BhbiBuYW1lIGFuZCBzYW1wbGUgcmF0ZSBhcmUgZXh0cmFjdGVkLgogKgogKiBAcmV0dXJucyBhIGR5bmFtaWMgc2FtcGxpbmcgY29udGV4dAogKi8KZnVuY3Rpb24gZ2V0RHluYW1pY1NhbXBsaW5nQ29udGV4dEZyb21TcGFuKHNwYW4pIHsKICBjb25zdCBjbGllbnQgPSBnZXRDbGllbnQoKTsKICBpZiAoIWNsaWVudCkgewogICAgcmV0dXJuIHt9OwogIH0KCiAgY29uc3QgZHNjID0gZ2V0RHluYW1pY1NhbXBsaW5nQ29udGV4dEZyb21DbGllbnQoc3BhblRvSlNPTihzcGFuKS50cmFjZV9pZCB8fCAnJywgY2xpZW50KTsKCiAgY29uc3Qgcm9vdFNwYW4gPSBnZXRSb290U3BhbihzcGFuKTsKICBpZiAoIXJvb3RTcGFuKSB7CiAgICByZXR1cm4gZHNjOwogIH0KCiAgY29uc3QgZnJvemVuRHNjID0gKHJvb3RTcGFuIClbRlJPWkVOX0RTQ19GSUVMRF07CiAgaWYgKGZyb3plbkRzYykgewogICAgcmV0dXJuIGZyb3plbkRzYzsKICB9CgogIGNvbnN0IGpzb25TcGFuID0gc3BhblRvSlNPTihyb290U3Bhbik7CiAgY29uc3QgYXR0cmlidXRlcyA9IGpzb25TcGFuLmRhdGEgfHwge307CiAgY29uc3QgbWF5YmVTYW1wbGVSYXRlID0gYXR0cmlidXRlc1tTRU1BTlRJQ19BVFRSSUJVVEVfU0VOVFJZX1NBTVBMRV9SQVRFXTsKCiAgaWYgKG1heWJlU2FtcGxlUmF0ZSAhPSBudWxsKSB7CiAgICBkc2Muc2FtcGxlX3JhdGUgPSBgJHttYXliZVNhbXBsZVJhdGV9YDsKICB9CgogIC8vIFdlIGRvbid0IHdhbnQgdG8gaGF2ZSBhIHRyYW5zYWN0aW9uIG5hbWUgaW4gdGhlIERTQyBpZiB0aGUgc291cmNlIGlzICJ1cmwiIGJlY2F1c2UgVVJMcyBtaWdodCBjb250YWluIFBJSQogIGNvbnN0IHNvdXJjZSA9IGF0dHJpYnV0ZXNbU0VNQU5USUNfQVRUUklCVVRFX1NFTlRSWV9TT1VSQ0VdOwoKICAvLyBhZnRlciBKU09OIGNvbnZlcnNpb24sIHR4bi5uYW1lIGJlY29tZXMganNvblNwYW4uZGVzY3JpcHRpb24KICBpZiAoc291cmNlICYmIHNvdXJjZSAhPT0gJ3VybCcpIHsKICAgIGRzYy50cmFuc2FjdGlvbiA9IGpzb25TcGFuLmRlc2NyaXB0aW9uOwogIH0KCiAgZHNjLnNhbXBsZWQgPSBTdHJpbmcoc3BhbklzU2FtcGxlZChyb290U3BhbikpOwoKICBjbGllbnQuZW1pdCgnY3JlYXRlRHNjJywgZHNjKTsKCiAgcmV0dXJuIGRzYzsKfQoKY29uc3QgU1VQUFJFU1NfVFJBQ0lOR19LRVkgPSAnX19TRU5UUllfU1VQUFJFU1NfVFJBQ0lOR19fJzsKCi8qKiBTdXBwcmVzcyB0cmFjaW5nIGluIHRoZSBnaXZlbiBjYWxsYmFjaywgZW5zdXJpbmcgbm8gc3BhbnMgYXJlIGdlbmVyYXRlZCBpbnNpZGUgb2YgaXQuICovCmZ1bmN0aW9uIHN1cHByZXNzVHJhY2luZyhjYWxsYmFjaykgewogIGNvbnN0IGFjcyA9IGdldEFjcygpOwoKICBpZiAoYWNzLnN1cHByZXNzVHJhY2luZykgewogICAgcmV0dXJuIGFjcy5zdXBwcmVzc1RyYWNpbmcoY2FsbGJhY2spOwogIH0KCiAgcmV0dXJuIHdpdGhTY29wZShzY29wZSA9PiB7CiAgICBzY29wZS5zZXRTREtQcm9jZXNzaW5nTWV0YWRhdGEoeyBbU1VQUFJFU1NfVFJBQ0lOR19LRVldOiB0cnVlIH0pOwogICAgcmV0dXJuIGNhbGxiYWNrKCk7CiAgfSk7Cn0KCmZ1bmN0aW9uIGdldEFjcygpIHsKICBjb25zdCBjYXJyaWVyID0gZ2V0TWFpbkNhcnJpZXIoKTsKICByZXR1cm4gZ2V0QXN5bmNDb250ZXh0U3RyYXRlZ3koY2Fycmllcik7Cn0KCi8qKgogKiBBcHBseSBTZGtJbmZvIChuYW1lLCB2ZXJzaW9uLCBwYWNrYWdlcywgaW50ZWdyYXRpb25zKSB0byB0aGUgY29ycmVzcG9uZGluZyBldmVudCBrZXkuCiAqIE1lcmdlIHdpdGggZXhpc3RpbmcgZGF0YSBpZiBhbnkuCiAqKi8KZnVuY3Rpb24gZW5oYW5jZUV2ZW50V2l0aFNka0luZm8oZXZlbnQsIHNka0luZm8pIHsKICBpZiAoIXNka0luZm8pIHsKICAgIHJldHVybiBldmVudDsKICB9CiAgZXZlbnQuc2RrID0gZXZlbnQuc2RrIHx8IHt9OwogIGV2ZW50LnNkay5uYW1lID0gZXZlbnQuc2RrLm5hbWUgfHwgc2RrSW5mby5uYW1lOwogIGV2ZW50LnNkay52ZXJzaW9uID0gZXZlbnQuc2RrLnZlcnNpb24gfHwgc2RrSW5mby52ZXJzaW9uOwogIGV2ZW50LnNkay5pbnRlZ3JhdGlvbnMgPSBbLi4uKGV2ZW50LnNkay5pbnRlZ3JhdGlvbnMgfHwgW10pLCAuLi4oc2RrSW5mby5pbnRlZ3JhdGlvbnMgfHwgW10pXTsKICBldmVudC5zZGsucGFja2FnZXMgPSBbLi4uKGV2ZW50LnNkay5wYWNrYWdlcyB8fCBbXSksIC4uLihzZGtJbmZvLnBhY2thZ2VzIHx8IFtdKV07CiAgcmV0dXJuIGV2ZW50Owp9CgovKiogQ3JlYXRlcyBhbiBlbnZlbG9wZSBmcm9tIGEgU2Vzc2lvbiAqLwpmdW5jdGlvbiBjcmVhdGVTZXNzaW9uRW52ZWxvcGUoCiAgc2Vzc2lvbiwKICBkc24sCiAgbWV0YWRhdGEsCiAgdHVubmVsLAopIHsKICBjb25zdCBzZGtJbmZvID0gZ2V0U2RrTWV0YWRhdGFGb3JFbnZlbG9wZUhlYWRlcihtZXRhZGF0YSk7CiAgY29uc3QgZW52ZWxvcGVIZWFkZXJzID0gewogICAgc2VudF9hdDogbmV3IERhdGUoKS50b0lTT1N0cmluZygpLAogICAgLi4uKHNka0luZm8gJiYgeyBzZGs6IHNka0luZm8gfSksCiAgICAuLi4oISF0dW5uZWwgJiYgZHNuICYmIHsgZHNuOiBkc25Ub1N0cmluZyhkc24pIH0pLAogIH07CgogIGNvbnN0IGVudmVsb3BlSXRlbSA9CiAgICAnYWdncmVnYXRlcycgaW4gc2Vzc2lvbiA/IFt7IHR5cGU6ICdzZXNzaW9ucycgfSwgc2Vzc2lvbl0gOiBbeyB0eXBlOiAnc2Vzc2lvbicgfSwgc2Vzc2lvbi50b0pTT04oKV07CgogIHJldHVybiBjcmVhdGVFbnZlbG9wZShlbnZlbG9wZUhlYWRlcnMsIFtlbnZlbG9wZUl0ZW1dKTsKfQoKLyoqCiAqIENyZWF0ZSBhbiBFbnZlbG9wZSBmcm9tIGFuIGV2ZW50LgogKi8KZnVuY3Rpb24gY3JlYXRlRXZlbnRFbnZlbG9wZSgKICBldmVudCwKICBkc24sCiAgbWV0YWRhdGEsCiAgdHVubmVsLAopIHsKICBjb25zdCBzZGtJbmZvID0gZ2V0U2RrTWV0YWRhdGFGb3JFbnZlbG9wZUhlYWRlcihtZXRhZGF0YSk7CgogIC8qCiAgICBOb3RlOiBEdWUgdG8gVFMsIGV2ZW50LnR5cGUgbWF5IGJlIGByZXBsYXlfZXZlbnRgLCB0aGVvcmV0aWNhbGx5LgogICAgSW4gcHJhY3RpY2UsIHdlIG5ldmVyIGNhbGwgYGNyZWF0ZUV2ZW50RW52ZWxvcGVgIHdpdGggYHJlcGxheV9ldmVudGAgdHlwZSwKICAgIGFuZCB3ZSdkIGhhdmUgdG8gYWRqdXQgYSBsb29vdCBvZiB0eXBlcyB0byBtYWtlIHRoaXMgd29yayBwcm9wZXJseS4KICAgIFdlIHdhbnQgdG8gYXZvaWQgY2FzdGluZyB0aGlzIGFyb3VuZCwgYXMgdGhhdCBjb3VsZCBsZWFkIHRvIGJ1Z3MgKGUuZy4gd2hlbiB3ZSBhZGQgYW5vdGhlciB0eXBlKQogICAgU28gdGhlIHNhZmUgY2hvaWNlIGlzIHRvIHJlYWxseSBndWFyZCBhZ2FpbnN0IHRoZSByZXBsYXlfZXZlbnQgdHlwZSBoZXJlLgogICovCiAgY29uc3QgZXZlbnRUeXBlID0gZXZlbnQudHlwZSAmJiBldmVudC50eXBlICE9PSAncmVwbGF5X2V2ZW50JyA/IGV2ZW50LnR5cGUgOiAnZXZlbnQnOwoKICBlbmhhbmNlRXZlbnRXaXRoU2RrSW5mbyhldmVudCwgbWV0YWRhdGEgJiYgbWV0YWRhdGEuc2RrKTsKCiAgY29uc3QgZW52ZWxvcGVIZWFkZXJzID0gY3JlYXRlRXZlbnRFbnZlbG9wZUhlYWRlcnMoZXZlbnQsIHNka0luZm8sIHR1bm5lbCwgZHNuKTsKCiAgLy8gUHJldmVudCB0aGlzIGRhdGEgKHdoaWNoLCBpZiBpdCBleGlzdHMsIHdhcyB1c2VkIGluIGVhcmxpZXIgc3RlcHMgaW4gdGhlIHByb2Nlc3NpbmcgcGlwZWxpbmUpIGZyb20gYmVpbmcgc2VudCB0bwogIC8vIHNlbnRyeS4gKE5vdGU6IE91ciB1c2Ugb2YgdGhpcyBwcm9wZXJ0eSBjb21lcyBhbmQgZ29lcyB3aXRoIHdoYXRldmVyIHdlIG1pZ2h0IGJlIGRlYnVnZ2luZywgd2hhdGV2ZXIgaGFja3Mgd2UgbWF5CiAgLy8gaGF2ZSB0ZW1wb3JhcmlseSBhZGRlZCwgZXRjLiBFdmVuIGlmIHdlIGRvbid0IGhhcHBlbiB0byBiZSB1c2luZyBpdCBhdCBzb21lIHBvaW50IGluIHRoZSBmdXR1cmUsIGxldCdzIG5vdCBnZXQgcmlkCiAgLy8gb2YgdGhpcyBgZGVsZXRlYCwgbGVzdCB3ZSBtaXNzIHB1dHRpbmcgaXQgYmFjayBpbiB0aGUgbmV4dCB0aW1lIHRoZSBwcm9wZXJ0eSBpcyBpbiB1c2UuKQogIGRlbGV0ZSBldmVudC5zZGtQcm9jZXNzaW5nTWV0YWRhdGE7CgogIGNvbnN0IGV2ZW50SXRlbSA9IFt7IHR5cGU6IGV2ZW50VHlwZSB9LCBldmVudF07CiAgcmV0dXJuIGNyZWF0ZUVudmVsb3BlKGVudmVsb3BlSGVhZGVycywgW2V2ZW50SXRlbV0pOwp9CgovKioKICogQXBwbGllcyBkYXRhIGZyb20gdGhlIHNjb3BlIHRvIHRoZSBldmVudCBhbmQgcnVucyBhbGwgZXZlbnQgcHJvY2Vzc29ycyBvbiBpdC4KICovCmZ1bmN0aW9uIGFwcGx5U2NvcGVEYXRhVG9FdmVudChldmVudCwgZGF0YSkgewogIGNvbnN0IHsgZmluZ2VycHJpbnQsIHNwYW4sIGJyZWFkY3J1bWJzLCBzZGtQcm9jZXNzaW5nTWV0YWRhdGEgfSA9IGRhdGE7CgogIC8vIEFwcGx5IGdlbmVyYWwgZGF0YQogIGFwcGx5RGF0YVRvRXZlbnQoZXZlbnQsIGRhdGEpOwoKICAvLyBXZSB3YW50IHRvIHNldCB0aGUgdHJhY2UgY29udGV4dCBmb3Igbm9ybWFsIGV2ZW50cyBvbmx5IGlmIHRoZXJlIGlzbid0IGFscmVhZHkKICAvLyBhIHRyYWNlIGNvbnRleHQgb24gdGhlIGV2ZW50LiBUaGVyZSBpcyBhIHByb2R1Y3QgZmVhdHVyZSBpbiBwbGFjZSB3aGVyZSB3ZSBsaW5rCiAgLy8gZXJyb3JzIHdpdGggdHJhbnNhY3Rpb24gYW5kIGl0IHJlbGllcyBvbiB0aGF0LgogIGlmIChzcGFuKSB7CiAgICBhcHBseVNwYW5Ub0V2ZW50KGV2ZW50LCBzcGFuKTsKICB9CgogIGFwcGx5RmluZ2VycHJpbnRUb0V2ZW50KGV2ZW50LCBmaW5nZXJwcmludCk7CiAgYXBwbHlCcmVhZGNydW1ic1RvRXZlbnQoZXZlbnQsIGJyZWFkY3J1bWJzKTsKICBhcHBseVNka01ldGFkYXRhVG9FdmVudChldmVudCwgc2RrUHJvY2Vzc2luZ01ldGFkYXRhKTsKfQoKZnVuY3Rpb24gYXBwbHlEYXRhVG9FdmVudChldmVudCwgZGF0YSkgewogIGNvbnN0IHsgZXh0cmEsIHRhZ3MsIHVzZXIsIGNvbnRleHRzLCBsZXZlbCwgdHJhbnNhY3Rpb25OYW1lIH0gPSBkYXRhOwoKICBjb25zdCBjbGVhbmVkRXh0cmEgPSBkcm9wVW5kZWZpbmVkS2V5cyhleHRyYSk7CiAgaWYgKGNsZWFuZWRFeHRyYSAmJiBPYmplY3Qua2V5cyhjbGVhbmVkRXh0cmEpLmxlbmd0aCkgewogICAgZXZlbnQuZXh0cmEgPSB7IC4uLmNsZWFuZWRFeHRyYSwgLi4uZXZlbnQuZXh0cmEgfTsKICB9CgogIGNvbnN0IGNsZWFuZWRUYWdzID0gZHJvcFVuZGVmaW5lZEtleXModGFncyk7CiAgaWYgKGNsZWFuZWRUYWdzICYmIE9iamVjdC5rZXlzKGNsZWFuZWRUYWdzKS5sZW5ndGgpIHsKICAgIGV2ZW50LnRhZ3MgPSB7IC4uLmNsZWFuZWRUYWdzLCAuLi5ldmVudC50YWdzIH07CiAgfQoKICBjb25zdCBjbGVhbmVkVXNlciA9IGRyb3BVbmRlZmluZWRLZXlzKHVzZXIpOwogIGlmIChjbGVhbmVkVXNlciAmJiBPYmplY3Qua2V5cyhjbGVhbmVkVXNlcikubGVuZ3RoKSB7CiAgICBldmVudC51c2VyID0geyAuLi5jbGVhbmVkVXNlciwgLi4uZXZlbnQudXNlciB9OwogIH0KCiAgY29uc3QgY2xlYW5lZENvbnRleHRzID0gZHJvcFVuZGVmaW5lZEtleXMoY29udGV4dHMpOwogIGlmIChjbGVhbmVkQ29udGV4dHMgJiYgT2JqZWN0LmtleXMoY2xlYW5lZENvbnRleHRzKS5sZW5ndGgpIHsKICAgIGV2ZW50LmNvbnRleHRzID0geyAuLi5jbGVhbmVkQ29udGV4dHMsIC4uLmV2ZW50LmNvbnRleHRzIH07CiAgfQoKICBpZiAobGV2ZWwpIHsKICAgIGV2ZW50LmxldmVsID0gbGV2ZWw7CiAgfQoKICAvLyB0cmFuc2FjdGlvbiBldmVudHMgZ2V0IHRoZWlyIGB0cmFuc2FjdGlvbmAgZnJvbSB0aGUgcm9vdCBzcGFuIG5hbWUKICBpZiAodHJhbnNhY3Rpb25OYW1lICYmIGV2ZW50LnR5cGUgIT09ICd0cmFuc2FjdGlvbicpIHsKICAgIGV2ZW50LnRyYW5zYWN0aW9uID0gdHJhbnNhY3Rpb25OYW1lOwogIH0KfQoKZnVuY3Rpb24gYXBwbHlCcmVhZGNydW1ic1RvRXZlbnQoZXZlbnQsIGJyZWFkY3J1bWJzKSB7CiAgY29uc3QgbWVyZ2VkQnJlYWRjcnVtYnMgPSBbLi4uKGV2ZW50LmJyZWFkY3J1bWJzIHx8IFtdKSwgLi4uYnJlYWRjcnVtYnNdOwogIGV2ZW50LmJyZWFkY3J1bWJzID0gbWVyZ2VkQnJlYWRjcnVtYnMubGVuZ3RoID8gbWVyZ2VkQnJlYWRjcnVtYnMgOiB1bmRlZmluZWQ7Cn0KCmZ1bmN0aW9uIGFwcGx5U2RrTWV0YWRhdGFUb0V2ZW50KGV2ZW50LCBzZGtQcm9jZXNzaW5nTWV0YWRhdGEpIHsKICBldmVudC5zZGtQcm9jZXNzaW5nTWV0YWRhdGEgPSB7CiAgICAuLi5ldmVudC5zZGtQcm9jZXNzaW5nTWV0YWRhdGEsCiAgICAuLi5zZGtQcm9jZXNzaW5nTWV0YWRhdGEsCiAgfTsKfQoKZnVuY3Rpb24gYXBwbHlTcGFuVG9FdmVudChldmVudCwgc3BhbikgewogIGV2ZW50LmNvbnRleHRzID0geyB0cmFjZTogc3BhblRvVHJhY2VDb250ZXh0KHNwYW4pLCAuLi5ldmVudC5jb250ZXh0cyB9OwoKICBldmVudC5zZGtQcm9jZXNzaW5nTWV0YWRhdGEgPSB7CiAgICBkeW5hbWljU2FtcGxpbmdDb250ZXh0OiBnZXREeW5hbWljU2FtcGxpbmdDb250ZXh0RnJvbVNwYW4oc3BhbiksCiAgICAuLi5ldmVudC5zZGtQcm9jZXNzaW5nTWV0YWRhdGEsCiAgfTsKCiAgY29uc3Qgcm9vdFNwYW4gPSBnZXRSb290U3BhbihzcGFuKTsKICBjb25zdCB0cmFuc2FjdGlvbk5hbWUgPSBzcGFuVG9KU09OKHJvb3RTcGFuKS5kZXNjcmlwdGlvbjsKICBpZiAodHJhbnNhY3Rpb25OYW1lICYmICFldmVudC50cmFuc2FjdGlvbiAmJiBldmVudC50eXBlID09PSAndHJhbnNhY3Rpb24nKSB7CiAgICBldmVudC50cmFuc2FjdGlvbiA9IHRyYW5zYWN0aW9uTmFtZTsKICB9Cn0KCi8qKgogKiBBcHBsaWVzIGZpbmdlcnByaW50IGZyb20gdGhlIHNjb3BlIHRvIHRoZSBldmVudCBpZiB0aGVyZSdzIG9uZSwKICogdXNlcyBtZXNzYWdlIGlmIHRoZXJlJ3Mgb25lIGluc3RlYWQgb3IgZ2V0IHJpZCBvZiBlbXB0eSBmaW5nZXJwcmludAogKi8KZnVuY3Rpb24gYXBwbHlGaW5nZXJwcmludFRvRXZlbnQoZXZlbnQsIGZpbmdlcnByaW50KSB7CiAgLy8gTWFrZSBzdXJlIGl0J3MgYW4gYXJyYXkgZmlyc3QgYW5kIHdlIGFjdHVhbGx5IGhhdmUgc29tZXRoaW5nIGluIHBsYWNlCiAgZXZlbnQuZmluZ2VycHJpbnQgPSBldmVudC5maW5nZXJwcmludCA/IGFycmF5aWZ5KGV2ZW50LmZpbmdlcnByaW50KSA6IFtdOwoKICAvLyBJZiB3ZSBoYXZlIHNvbWV0aGluZyBvbiB0aGUgc2NvcGUsIHRoZW4gbWVyZ2UgaXQgd2l0aCBldmVudAogIGlmIChmaW5nZXJwcmludCkgewogICAgZXZlbnQuZmluZ2VycHJpbnQgPSBldmVudC5maW5nZXJwcmludC5jb25jYXQoZmluZ2VycHJpbnQpOwogIH0KCiAgLy8gSWYgd2UgaGF2ZSBubyBkYXRhIGF0IGFsbCwgcmVtb3ZlIGVtcHR5IGFycmF5IGRlZmF1bHQKICBpZiAoZXZlbnQuZmluZ2VycHJpbnQgJiYgIWV2ZW50LmZpbmdlcnByaW50Lmxlbmd0aCkgewogICAgZGVsZXRlIGV2ZW50LmZpbmdlcnByaW50OwogIH0KfQoKY29uc3QgU0VOVFJZX0FQSV9WRVJTSU9OID0gJzcnOwoKLyoqIFJldHVybnMgdGhlIHByZWZpeCB0byBjb25zdHJ1Y3QgU2VudHJ5IGluZ2VzdGlvbiBBUEkgZW5kcG9pbnRzLiAqLwpmdW5jdGlvbiBnZXRCYXNlQXBpRW5kcG9pbnQoZHNuKSB7CiAgY29uc3QgcHJvdG9jb2wgPSBkc24ucHJvdG9jb2wgPyBgJHtkc24ucHJvdG9jb2x9OmAgOiAnJzsKICBjb25zdCBwb3J0ID0gZHNuLnBvcnQgPyBgOiR7ZHNuLnBvcnR9YCA6ICcnOwogIHJldHVybiBgJHtwcm90b2NvbH0vLyR7ZHNuLmhvc3R9JHtwb3J0fSR7ZHNuLnBhdGggPyBgLyR7ZHNuLnBhdGh9YCA6ICcnfS9hcGkvYDsKfQoKLyoqIFJldHVybnMgdGhlIGluZ2VzdCBBUEkgZW5kcG9pbnQgZm9yIHRhcmdldC4gKi8KZnVuY3Rpb24gX2dldEluZ2VzdEVuZHBvaW50KGRzbikgewogIHJldHVybiBgJHtnZXRCYXNlQXBpRW5kcG9pbnQoZHNuKX0ke2Rzbi5wcm9qZWN0SWR9L2VudmVsb3BlL2A7Cn0KCi8qKiBSZXR1cm5zIGEgVVJMLWVuY29kZWQgc3RyaW5nIHdpdGggYXV0aCBjb25maWcgc3VpdGFibGUgZm9yIGEgcXVlcnkgc3RyaW5nLiAqLwpmdW5jdGlvbiBfZW5jb2RlZEF1dGgoZHNuLCBzZGtJbmZvKSB7CiAgcmV0dXJuIHVybEVuY29kZSh7CiAgICAvLyBXZSBzZW5kIG9ubHkgdGhlIG1pbmltdW0gc2V0IG9mIHJlcXVpcmVkIGluZm9ybWF0aW9uLiBTZWUKICAgIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9nZXRzZW50cnkvc2VudHJ5LWphdmFzY3JpcHQvaXNzdWVzLzI1NzIuCiAgICBzZW50cnlfa2V5OiBkc24ucHVibGljS2V5LAogICAgc2VudHJ5X3ZlcnNpb246IFNFTlRSWV9BUElfVkVSU0lPTiwKICAgIC4uLihzZGtJbmZvICYmIHsgc2VudHJ5X2NsaWVudDogYCR7c2RrSW5mby5uYW1lfS8ke3Nka0luZm8udmVyc2lvbn1gIH0pLAogIH0pOwp9CgovKioKICogUmV0dXJucyB0aGUgZW52ZWxvcGUgZW5kcG9pbnQgVVJMIHdpdGggYXV0aCBpbiB0aGUgcXVlcnkgc3RyaW5nLgogKgogKiBTZW5kaW5nIGF1dGggYXMgcGFydCBvZiB0aGUgcXVlcnkgc3RyaW5nIGFuZCBub3QgYXMgY3VzdG9tIEhUVFAgaGVhZGVycyBhdm9pZHMgQ09SUyBwcmVmbGlnaHQgcmVxdWVzdHMuCiAqLwpmdW5jdGlvbiBnZXRFbnZlbG9wZUVuZHBvaW50V2l0aFVybEVuY29kZWRBdXRoKGRzbiwgdHVubmVsLCBzZGtJbmZvKSB7CiAgcmV0dXJuIHR1bm5lbCA/IHR1bm5lbCA6IGAke19nZXRJbmdlc3RFbmRwb2ludChkc24pfT8ke19lbmNvZGVkQXV0aChkc24sIHNka0luZm8pfWA7Cn0KCmNvbnN0IERFRkFVTFRfVFJBTlNQT1JUX0JVRkZFUl9TSVpFID0gMzA7CgovKioKICogQ3JlYXRlcyBhbiBpbnN0YW5jZSBvZiBhIFNlbnRyeSBgVHJhbnNwb3J0YAogKgogKiBAcGFyYW0gb3B0aW9ucwogKiBAcGFyYW0gbWFrZVJlcXVlc3QKICovCmZ1bmN0aW9uIGNyZWF0ZVRyYW5zcG9ydCgKICBvcHRpb25zLAogIG1ha2VSZXF1ZXN0LAogIGJ1ZmZlciA9IG1ha2VQcm9taXNlQnVmZmVyKAogICAgb3B0aW9ucy5idWZmZXJTaXplIHx8IERFRkFVTFRfVFJBTlNQT1JUX0JVRkZFUl9TSVpFLAogICksCikgewogIGxldCByYXRlTGltaXRzID0ge307CiAgY29uc3QgZmx1c2ggPSAodGltZW91dCkgPT4gYnVmZmVyLmRyYWluKHRpbWVvdXQpOwoKICBmdW5jdGlvbiBzZW5kKGVudmVsb3BlKSB7CiAgICBjb25zdCBmaWx0ZXJlZEVudmVsb3BlSXRlbXMgPSBbXTsKCiAgICAvLyBEcm9wIHJhdGUgbGltaXRlZCBpdGVtcyBmcm9tIGVudmVsb3BlCiAgICBmb3JFYWNoRW52ZWxvcGVJdGVtKGVudmVsb3BlLCAoaXRlbSwgdHlwZSkgPT4gewogICAgICBjb25zdCBkYXRhQ2F0ZWdvcnkgPSBlbnZlbG9wZUl0ZW1UeXBlVG9EYXRhQ2F0ZWdvcnkodHlwZSk7CiAgICAgIGlmIChpc1JhdGVMaW1pdGVkKHJhdGVMaW1pdHMsIGRhdGFDYXRlZ29yeSkpIHsKICAgICAgICBjb25zdCBldmVudCA9IGdldEV2ZW50Rm9yRW52ZWxvcGVJdGVtKGl0ZW0sIHR5cGUpOwogICAgICAgIG9wdGlvbnMucmVjb3JkRHJvcHBlZEV2ZW50KCdyYXRlbGltaXRfYmFja29mZicsIGRhdGFDYXRlZ29yeSwgZXZlbnQpOwogICAgICB9IGVsc2UgewogICAgICAgIGZpbHRlcmVkRW52ZWxvcGVJdGVtcy5wdXNoKGl0ZW0pOwogICAgICB9CiAgICB9KTsKCiAgICAvLyBTa2lwIHNlbmRpbmcgaWYgZW52ZWxvcGUgaXMgZW1wdHkgYWZ0ZXIgZmlsdGVyaW5nIG91dCByYXRlIGxpbWl0ZWQgZXZlbnRzCiAgICBpZiAoZmlsdGVyZWRFbnZlbG9wZUl0ZW1zLmxlbmd0aCA9PT0gMCkgewogICAgICByZXR1cm4gcmVzb2x2ZWRTeW5jUHJvbWlzZSh7fSk7CiAgICB9CgogICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnkKICAgIGNvbnN0IGZpbHRlcmVkRW52ZWxvcGUgPSBjcmVhdGVFbnZlbG9wZShlbnZlbG9wZVswXSwgZmlsdGVyZWRFbnZlbG9wZUl0ZW1zICk7CgogICAgLy8gQ3JlYXRlcyBjbGllbnQgcmVwb3J0IGZvciBlYWNoIGl0ZW0gaW4gYW4gZW52ZWxvcGUKICAgIGNvbnN0IHJlY29yZEVudmVsb3BlTG9zcyA9IChyZWFzb24pID0+IHsKICAgICAgZm9yRWFjaEVudmVsb3BlSXRlbShmaWx0ZXJlZEVudmVsb3BlLCAoaXRlbSwgdHlwZSkgPT4gewogICAgICAgIGNvbnN0IGV2ZW50ID0gZ2V0RXZlbnRGb3JFbnZlbG9wZUl0ZW0oaXRlbSwgdHlwZSk7CiAgICAgICAgb3B0aW9ucy5yZWNvcmREcm9wcGVkRXZlbnQocmVhc29uLCBlbnZlbG9wZUl0ZW1UeXBlVG9EYXRhQ2F0ZWdvcnkodHlwZSksIGV2ZW50KTsKICAgICAgfSk7CiAgICB9OwoKICAgIGNvbnN0IHJlcXVlc3RUYXNrID0gKCkgPT4KICAgICAgbWFrZVJlcXVlc3QoeyBib2R5OiBzZXJpYWxpemVFbnZlbG9wZShmaWx0ZXJlZEVudmVsb3BlKSB9KS50aGVuKAogICAgICAgIHJlc3BvbnNlID0+IHsKICAgICAgICAgIC8vIFdlIGRvbid0IHdhbnQgdG8gdGhyb3cgb24gTk9LIHJlc3BvbnNlcywgYnV0IHdlIHdhbnQgdG8gYXQgbGVhc3QgbG9nIHRoZW0KICAgICAgICAgIGlmIChyZXNwb25zZS5zdGF0dXNDb2RlICE9PSB1bmRlZmluZWQgJiYgKHJlc3BvbnNlLnN0YXR1c0NvZGUgPCAyMDAgfHwgcmVzcG9uc2Uuc3RhdHVzQ29kZSA+PSAzMDApKSB7CiAgICAgICAgICAgIERFQlVHX0JVSUxEICYmIGxvZ2dlci53YXJuKGBTZW50cnkgcmVzcG9uZGVkIHdpdGggc3RhdHVzIGNvZGUgJHtyZXNwb25zZS5zdGF0dXNDb2RlfSB0byBzZW50IGV2ZW50LmApOwogICAgICAgICAgfQoKICAgICAgICAgIHJhdGVMaW1pdHMgPSB1cGRhdGVSYXRlTGltaXRzKHJhdGVMaW1pdHMsIHJlc3BvbnNlKTsKICAgICAgICAgIHJldHVybiByZXNwb25zZTsKICAgICAgICB9LAogICAgICAgIGVycm9yID0+IHsKICAgICAgICAgIHJlY29yZEVudmVsb3BlTG9zcygnbmV0d29ya19lcnJvcicpOwogICAgICAgICAgdGhyb3cgZXJyb3I7CiAgICAgICAgfSwKICAgICAgKTsKCiAgICByZXR1cm4gYnVmZmVyLmFkZChyZXF1ZXN0VGFzaykudGhlbigKICAgICAgcmVzdWx0ID0+IHJlc3VsdCwKICAgICAgZXJyb3IgPT4gewogICAgICAgIGlmIChlcnJvciBpbnN0YW5jZW9mIFNlbnRyeUVycm9yKSB7CiAgICAgICAgICBERUJVR19CVUlMRCAmJiBsb2dnZXIuZXJyb3IoJ1NraXBwZWQgc2VuZGluZyBldmVudCBiZWNhdXNlIGJ1ZmZlciBpcyBmdWxsLicpOwogICAgICAgICAgcmVjb3JkRW52ZWxvcGVMb3NzKCdxdWV1ZV9vdmVyZmxvdycpOwogICAgICAgICAgcmV0dXJuIHJlc29sdmVkU3luY1Byb21pc2Uoe30pOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICB0aHJvdyBlcnJvcjsKICAgICAgICB9CiAgICAgIH0sCiAgICApOwogIH0KCiAgcmV0dXJuIHsKICAgIHNlbmQsCiAgICBmbHVzaCwKICB9Owp9CgpmdW5jdGlvbiBnZXRFdmVudEZvckVudmVsb3BlSXRlbShpdGVtLCB0eXBlKSB7CiAgaWYgKHR5cGUgIT09ICdldmVudCcgJiYgdHlwZSAhPT0gJ3RyYW5zYWN0aW9uJykgewogICAgcmV0dXJuIHVuZGVmaW5lZDsKICB9CgogIHJldHVybiBBcnJheS5pc0FycmF5KGl0ZW0pID8gKGl0ZW0gKVsxXSA6IHVuZGVmaW5lZDsKfQoKZnVuY3Rpb24gX251bGxpc2hDb2FsZXNjZSQyKGxocywgcmhzRm4pIHsgaWYgKGxocyAhPSBudWxsKSB7IHJldHVybiBsaHM7IH0gZWxzZSB7IHJldHVybiByaHNGbigpOyB9IH0vKioKICogVGhpcyBjb2RlIHdhcyBvcmlnaW5hbGx5IGZvcmtlZCBmcm9tIGh0dHBzOi8vZ2l0aHViLmNvbS9Ub29UYWxsTmF0ZS9wcm94eS1hZ2VudHMvdHJlZS9iMTMzMjk1ZmQxNmY2NDc1NTc4YjZiMTViZDliNGUzM2VjYjBkMGI3CiAqIFdpdGggdGhlIGZvbGxvd2luZyBsaWNlbmNlOgogKgogKiAoVGhlIE1JVCBMaWNlbnNlKQogKgogKiBDb3B5cmlnaHQgKGMpIDIwMTMgTmF0aGFuIFJhamxpY2ggPG5hdGhhbkB0b290YWxsbmF0ZS5uZXQ+KgogKgogKiBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcKICogYSBjb3B5IG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlCiAqICdTb2Z0d2FyZScpLCB0byBkZWFsIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmcKICogd2l0aG91dCBsaW1pdGF0aW9uIHRoZSByaWdodHMgdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLAogKiBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbCBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8KICogcGVybWl0IHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXMgZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvCiAqIHRoZSBmb2xsb3dpbmcgY29uZGl0aW9uczoqCiAqCiAqIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlCiAqIGluY2x1ZGVkIGluIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLioKICoKICogVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEICdBUyBJUycsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsCiAqIEVYUFJFU1MgT1IgSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRgogKiBNRVJDSEFOVEFCSUxJVFksIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuCiAqIElOIE5PIEVWRU5UIFNIQUxMIFRIRSBBVVRIT1JTIE9SIENPUFlSSUdIVCBIT0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZCiAqIENMQUlNLCBEQU1BR0VTIE9SIE9USEVSIExJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsCiAqIFRPUlQgT1IgT1RIRVJXSVNFLCBBUklTSU5HIEZST00sIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFCiAqIFNPRlRXQVJFIE9SIFRIRSBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU4gVEhFIFNPRlRXQVJFLgogKi8KCmNvbnN0IElOVEVSTkFMID0gU3ltYm9sKCdBZ2VudEJhc2VJbnRlcm5hbFN0YXRlJyk7CgpjbGFzcyBBZ2VudCBleHRlbmRzIGh0dHAuQWdlbnQgewoKICAvLyBTZXQgYnkgYGh0dHAuQWdlbnRgIC0gbWlzc2luZyBmcm9tIGBAdHlwZXMvbm9kZWAKCiAgY29uc3RydWN0b3Iob3B0cykgewogICAgc3VwZXIob3B0cyk7CiAgICB0aGlzW0lOVEVSTkFMXSA9IHt9OwogIH0KCiAgLyoqCiAgICogRGV0ZXJtaW5lIHdoZXRoZXIgdGhpcyBpcyBhbiBgaHR0cGAgb3IgYGh0dHBzYCByZXF1ZXN0LgogICAqLwogIGlzU2VjdXJlRW5kcG9pbnQob3B0aW9ucykgewogICAgaWYgKG9wdGlvbnMpIHsKICAgICAgLy8gRmlyc3QgY2hlY2sgdGhlIGBzZWN1cmVFbmRwb2ludGAgcHJvcGVydHkgZXhwbGljaXRseSwgc2luY2UgdGhpcwogICAgICAvLyBtZWFucyB0aGF0IGEgcGFyZW50IGBBZ2VudGAgaXMgInBhc3NpbmcgdGhyb3VnaCIgdG8gdGhpcyBpbnN0YW5jZS4KICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnksIEB0eXBlc2NyaXB0LWVzbGludC9uby11bnNhZmUtbWVtYmVyLWFjY2VzcwogICAgICBpZiAodHlwZW9mIChvcHRpb25zICkuc2VjdXJlRW5kcG9pbnQgPT09ICdib29sZWFuJykgewogICAgICAgIHJldHVybiBvcHRpb25zLnNlY3VyZUVuZHBvaW50OwogICAgICB9CgogICAgICAvLyBJZiBubyBleHBsaWNpdCBgc2VjdXJlYCBlbmRwb2ludCwgY2hlY2sgaWYgYHByb3RvY29sYCBwcm9wZXJ0eSBpcwogICAgICAvLyBzZXQuIFRoaXMgd2lsbCB1c3VhbGx5IGJlIHRoZSBjYXNlIHNpbmNlIHVzaW5nIGEgZnVsbCBzdHJpbmcgVVJMCiAgICAgIC8vIG9yIGBVUkxgIGluc3RhbmNlIHNob3VsZCBiZSB0aGUgbW9zdCBjb21tb24gdXNhZ2UuCiAgICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5wcm90b2NvbCA9PT0gJ3N0cmluZycpIHsKICAgICAgICByZXR1cm4gb3B0aW9ucy5wcm90b2NvbCA9PT0gJ2h0dHBzOic7CiAgICAgIH0KICAgIH0KCiAgICAvLyBGaW5hbGx5LCBpZiBubyBgcHJvdG9jb2xgIHByb3BlcnR5IHdhcyBzZXQsIHRoZW4gZmFsbCBiYWNrIHRvCiAgICAvLyBjaGVja2luZyB0aGUgc3RhY2sgdHJhY2Ugb2YgdGhlIGN1cnJlbnQgY2FsbCBzdGFjaywgYW5kIHRyeSB0bwogICAgLy8gZGV0ZWN0IHRoZSAiaHR0cHMiIG1vZHVsZS4KICAgIGNvbnN0IHsgc3RhY2sgfSA9IG5ldyBFcnJvcigpOwogICAgaWYgKHR5cGVvZiBzdGFjayAhPT0gJ3N0cmluZycpIHJldHVybiBmYWxzZTsKICAgIHJldHVybiBzdGFjay5zcGxpdCgnXG4nKS5zb21lKGwgPT4gbC5pbmRleE9mKCcoaHR0cHMuanM6JykgIT09IC0xIHx8IGwuaW5kZXhPZignbm9kZTpodHRwczonKSAhPT0gLTEpOwogIH0KCiAgY3JlYXRlU29ja2V0KHJlcSwgb3B0aW9ucywgY2IpIHsKICAgIGNvbnN0IGNvbm5lY3RPcHRzID0gewogICAgICAuLi5vcHRpb25zLAogICAgICBzZWN1cmVFbmRwb2ludDogdGhpcy5pc1NlY3VyZUVuZHBvaW50KG9wdGlvbnMpLAogICAgfTsKICAgIFByb21pc2UucmVzb2x2ZSgpCiAgICAgIC50aGVuKCgpID0+IHRoaXMuY29ubmVjdChyZXEsIGNvbm5lY3RPcHRzKSkKICAgICAgLnRoZW4oc29ja2V0ID0+IHsKICAgICAgICBpZiAoc29ja2V0IGluc3RhbmNlb2YgaHR0cC5BZ2VudCkgewogICAgICAgICAgLy8gQHRzLWV4cGVjdC1lcnJvciBgYWRkUmVxdWVzdCgpYCBpc24ndCBkZWZpbmVkIGluIGBAdHlwZXMvbm9kZWAKICAgICAgICAgIHJldHVybiBzb2NrZXQuYWRkUmVxdWVzdChyZXEsIGNvbm5lY3RPcHRzKTsKICAgICAgICB9CiAgICAgICAgdGhpc1tJTlRFUk5BTF0uY3VycmVudFNvY2tldCA9IHNvY2tldDsKICAgICAgICAvLyBAdHMtZXhwZWN0LWVycm9yIGBjcmVhdGVTb2NrZXQoKWAgaXNuJ3QgZGVmaW5lZCBpbiBgQHR5cGVzL25vZGVgCiAgICAgICAgc3VwZXIuY3JlYXRlU29ja2V0KHJlcSwgb3B0aW9ucywgY2IpOwogICAgICB9LCBjYik7CiAgfQoKICBjcmVhdGVDb25uZWN0aW9uKCkgewogICAgY29uc3Qgc29ja2V0ID0gdGhpc1tJTlRFUk5BTF0uY3VycmVudFNvY2tldDsKICAgIHRoaXNbSU5URVJOQUxdLmN1cnJlbnRTb2NrZXQgPSB1bmRlZmluZWQ7CiAgICBpZiAoIXNvY2tldCkgewogICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vIHNvY2tldCB3YXMgcmV0dXJuZWQgaW4gdGhlIGBjb25uZWN0KClgIGZ1bmN0aW9uJyk7CiAgICB9CiAgICByZXR1cm4gc29ja2V0OwogIH0KCiAgZ2V0IGRlZmF1bHRQb3J0KCkgewogICAgcmV0dXJuIF9udWxsaXNoQ29hbGVzY2UkMih0aGlzW0lOVEVSTkFMXS5kZWZhdWx0UG9ydCwgKCkgPT4gKCAodGhpcy5wcm90b2NvbCA9PT0gJ2h0dHBzOicgPyA0NDMgOiA4MCkpKTsKICB9CgogIHNldCBkZWZhdWx0UG9ydCh2KSB7CiAgICBpZiAodGhpc1tJTlRFUk5BTF0pIHsKICAgICAgdGhpc1tJTlRFUk5BTF0uZGVmYXVsdFBvcnQgPSB2OwogICAgfQogIH0KCiAgZ2V0IHByb3RvY29sKCkgewogICAgcmV0dXJuIF9udWxsaXNoQ29hbGVzY2UkMih0aGlzW0lOVEVSTkFMXS5wcm90b2NvbCwgKCkgPT4gKCAodGhpcy5pc1NlY3VyZUVuZHBvaW50KCkgPyAnaHR0cHM6JyA6ICdodHRwOicpKSk7CiAgfQoKICBzZXQgcHJvdG9jb2wodikgewogICAgaWYgKHRoaXNbSU5URVJOQUxdKSB7CiAgICAgIHRoaXNbSU5URVJOQUxdLnByb3RvY29sID0gdjsKICAgIH0KICB9Cn0KCmZ1bmN0aW9uIGRlYnVnJDEoLi4uYXJncykgewogIGxvZ2dlci5sb2coJ1todHRwcy1wcm94eS1hZ2VudDpwYXJzZS1wcm94eS1yZXNwb25zZV0nLCAuLi5hcmdzKTsKfQoKZnVuY3Rpb24gcGFyc2VQcm94eVJlc3BvbnNlKHNvY2tldCkgewogIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7CiAgICAvLyB3ZSBuZWVkIHRvIGJ1ZmZlciBhbnkgSFRUUCB0cmFmZmljIHRoYXQgaGFwcGVucyB3aXRoIHRoZSBwcm94eSBiZWZvcmUgd2UgZ2V0CiAgICAvLyB0aGUgQ09OTkVDVCByZXNwb25zZSwgc28gdGhhdCBpZiB0aGUgcmVzcG9uc2UgaXMgYW55dGhpbmcgb3RoZXIgdGhhbiBhbiAiMjAwIgogICAgLy8gcmVzcG9uc2UgY29kZSwgdGhlbiB3ZSBjYW4gcmUtcGxheSB0aGUgImRhdGEiIGV2ZW50cyBvbiB0aGUgc29ja2V0IG9uY2UgdGhlCiAgICAvLyBIVFRQIHBhcnNlciBpcyBob29rZWQgdXAuLi4KICAgIGxldCBidWZmZXJzTGVuZ3RoID0gMDsKICAgIGNvbnN0IGJ1ZmZlcnMgPSBbXTsKCiAgICBmdW5jdGlvbiByZWFkKCkgewogICAgICBjb25zdCBiID0gc29ja2V0LnJlYWQoKTsKICAgICAgaWYgKGIpIG9uZGF0YShiKTsKICAgICAgZWxzZSBzb2NrZXQub25jZSgncmVhZGFibGUnLCByZWFkKTsKICAgIH0KCiAgICBmdW5jdGlvbiBjbGVhbnVwKCkgewogICAgICBzb2NrZXQucmVtb3ZlTGlzdGVuZXIoJ2VuZCcsIG9uZW5kKTsKICAgICAgc29ja2V0LnJlbW92ZUxpc3RlbmVyKCdlcnJvcicsIG9uZXJyb3IpOwogICAgICBzb2NrZXQucmVtb3ZlTGlzdGVuZXIoJ3JlYWRhYmxlJywgcmVhZCk7CiAgICB9CgogICAgZnVuY3Rpb24gb25lbmQoKSB7CiAgICAgIGNsZWFudXAoKTsKICAgICAgZGVidWckMSgnb25lbmQnKTsKICAgICAgcmVqZWN0KG5ldyBFcnJvcignUHJveHkgY29ubmVjdGlvbiBlbmRlZCBiZWZvcmUgcmVjZWl2aW5nIENPTk5FQ1QgcmVzcG9uc2UnKSk7CiAgICB9CgogICAgZnVuY3Rpb24gb25lcnJvcihlcnIpIHsKICAgICAgY2xlYW51cCgpOwogICAgICBkZWJ1ZyQxKCdvbmVycm9yICVvJywgZXJyKTsKICAgICAgcmVqZWN0KGVycik7CiAgICB9CgogICAgZnVuY3Rpb24gb25kYXRhKGIpIHsKICAgICAgYnVmZmVycy5wdXNoKGIpOwogICAgICBidWZmZXJzTGVuZ3RoICs9IGIubGVuZ3RoOwoKICAgICAgY29uc3QgYnVmZmVyZWQgPSBCdWZmZXIuY29uY2F0KGJ1ZmZlcnMsIGJ1ZmZlcnNMZW5ndGgpOwogICAgICBjb25zdCBlbmRPZkhlYWRlcnMgPSBidWZmZXJlZC5pbmRleE9mKCdcclxuXHJcbicpOwoKICAgICAgaWYgKGVuZE9mSGVhZGVycyA9PT0gLTEpIHsKICAgICAgICAvLyBrZWVwIGJ1ZmZlcmluZwogICAgICAgIGRlYnVnJDEoJ2hhdmUgbm90IHJlY2VpdmVkIGVuZCBvZiBIVFRQIGhlYWRlcnMgeWV0Li4uJyk7CiAgICAgICAgcmVhZCgpOwogICAgICAgIHJldHVybjsKICAgICAgfQoKICAgICAgY29uc3QgaGVhZGVyUGFydHMgPSBidWZmZXJlZC5zbGljZSgwLCBlbmRPZkhlYWRlcnMpLnRvU3RyaW5nKCdhc2NpaScpLnNwbGl0KCdcclxuJyk7CiAgICAgIGNvbnN0IGZpcnN0TGluZSA9IGhlYWRlclBhcnRzLnNoaWZ0KCk7CiAgICAgIGlmICghZmlyc3RMaW5lKSB7CiAgICAgICAgc29ja2V0LmRlc3Ryb3koKTsKICAgICAgICByZXR1cm4gcmVqZWN0KG5ldyBFcnJvcignTm8gaGVhZGVyIHJlY2VpdmVkIGZyb20gcHJveHkgQ09OTkVDVCByZXNwb25zZScpKTsKICAgICAgfQogICAgICBjb25zdCBmaXJzdExpbmVQYXJ0cyA9IGZpcnN0TGluZS5zcGxpdCgnICcpOwogICAgICBjb25zdCBzdGF0dXNDb2RlID0gK2ZpcnN0TGluZVBhcnRzWzFdOwogICAgICBjb25zdCBzdGF0dXNUZXh0ID0gZmlyc3RMaW5lUGFydHMuc2xpY2UoMikuam9pbignICcpOwogICAgICBjb25zdCBoZWFkZXJzID0ge307CiAgICAgIGZvciAoY29uc3QgaGVhZGVyIG9mIGhlYWRlclBhcnRzKSB7CiAgICAgICAgaWYgKCFoZWFkZXIpIGNvbnRpbnVlOwogICAgICAgIGNvbnN0IGZpcnN0Q29sb24gPSBoZWFkZXIuaW5kZXhPZignOicpOwogICAgICAgIGlmIChmaXJzdENvbG9uID09PSAtMSkgewogICAgICAgICAgc29ja2V0LmRlc3Ryb3koKTsKICAgICAgICAgIHJldHVybiByZWplY3QobmV3IEVycm9yKGBJbnZhbGlkIGhlYWRlciBmcm9tIHByb3h5IENPTk5FQ1QgcmVzcG9uc2U6ICIke2hlYWRlcn0iYCkpOwogICAgICAgIH0KICAgICAgICBjb25zdCBrZXkgPSBoZWFkZXIuc2xpY2UoMCwgZmlyc3RDb2xvbikudG9Mb3dlckNhc2UoKTsKICAgICAgICBjb25zdCB2YWx1ZSA9IGhlYWRlci5zbGljZShmaXJzdENvbG9uICsgMSkudHJpbVN0YXJ0KCk7CiAgICAgICAgY29uc3QgY3VycmVudCA9IGhlYWRlcnNba2V5XTsKICAgICAgICBpZiAodHlwZW9mIGN1cnJlbnQgPT09ICdzdHJpbmcnKSB7CiAgICAgICAgICBoZWFkZXJzW2tleV0gPSBbY3VycmVudCwgdmFsdWVdOwogICAgICAgIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheShjdXJyZW50KSkgewogICAgICAgICAgY3VycmVudC5wdXNoKHZhbHVlKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgaGVhZGVyc1trZXldID0gdmFsdWU7CiAgICAgICAgfQogICAgICB9CiAgICAgIGRlYnVnJDEoJ2dvdCBwcm94eSBzZXJ2ZXIgcmVzcG9uc2U6ICVvICVvJywgZmlyc3RMaW5lLCBoZWFkZXJzKTsKICAgICAgY2xlYW51cCgpOwogICAgICByZXNvbHZlKHsKICAgICAgICBjb25uZWN0OiB7CiAgICAgICAgICBzdGF0dXNDb2RlLAogICAgICAgICAgc3RhdHVzVGV4dCwKICAgICAgICAgIGhlYWRlcnMsCiAgICAgICAgfSwKICAgICAgICBidWZmZXJlZCwKICAgICAgfSk7CiAgICB9CgogICAgc29ja2V0Lm9uKCdlcnJvcicsIG9uZXJyb3IpOwogICAgc29ja2V0Lm9uKCdlbmQnLCBvbmVuZCk7CgogICAgcmVhZCgpOwogIH0pOwp9CgpmdW5jdGlvbiBfbnVsbGlzaENvYWxlc2NlJDEobGhzLCByaHNGbikgeyBpZiAobGhzICE9IG51bGwpIHsgcmV0dXJuIGxoczsgfSBlbHNlIHsgcmV0dXJuIHJoc0ZuKCk7IH0gfSBmdW5jdGlvbiBfb3B0aW9uYWxDaGFpbiQxKG9wcykgeyBsZXQgbGFzdEFjY2Vzc0xIUyA9IHVuZGVmaW5lZDsgbGV0IHZhbHVlID0gb3BzWzBdOyBsZXQgaSA9IDE7IHdoaWxlIChpIDwgb3BzLmxlbmd0aCkgeyBjb25zdCBvcCA9IG9wc1tpXTsgY29uc3QgZm4gPSBvcHNbaSArIDFdOyBpICs9IDI7IGlmICgob3AgPT09ICdvcHRpb25hbEFjY2VzcycgfHwgb3AgPT09ICdvcHRpb25hbENhbGwnKSAmJiB2YWx1ZSA9PSBudWxsKSB7IHJldHVybiB1bmRlZmluZWQ7IH0gaWYgKG9wID09PSAnYWNjZXNzJyB8fCBvcCA9PT0gJ29wdGlvbmFsQWNjZXNzJykgeyBsYXN0QWNjZXNzTEhTID0gdmFsdWU7IHZhbHVlID0gZm4odmFsdWUpOyB9IGVsc2UgaWYgKG9wID09PSAnY2FsbCcgfHwgb3AgPT09ICdvcHRpb25hbENhbGwnKSB7IHZhbHVlID0gZm4oKC4uLmFyZ3MpID0+IHZhbHVlLmNhbGwobGFzdEFjY2Vzc0xIUywgLi4uYXJncykpOyBsYXN0QWNjZXNzTEhTID0gdW5kZWZpbmVkOyB9IH0gcmV0dXJuIHZhbHVlOyB9CgpmdW5jdGlvbiBkZWJ1ZyguLi5hcmdzKSB7CiAgbG9nZ2VyLmxvZygnW2h0dHBzLXByb3h5LWFnZW50XScsIC4uLmFyZ3MpOwp9CgovKioKICogVGhlIGBIdHRwc1Byb3h5QWdlbnRgIGltcGxlbWVudHMgYW4gSFRUUCBBZ2VudCBzdWJjbGFzcyB0aGF0IGNvbm5lY3RzIHRvCiAqIHRoZSBzcGVjaWZpZWQgIkhUVFAocykgcHJveHkgc2VydmVyIiBpbiBvcmRlciB0byBwcm94eSBIVFRQUyByZXF1ZXN0cy4KICoKICogT3V0Z29pbmcgSFRUUCByZXF1ZXN0cyBhcmUgZmlyc3QgdHVubmVsZWQgdGhyb3VnaCB0aGUgcHJveHkgc2VydmVyIHVzaW5nIHRoZQogKiBgQ09OTkVDVGAgSFRUUCByZXF1ZXN0IG1ldGhvZCB0byBlc3RhYmxpc2ggYSBjb25uZWN0aW9uIHRvIHRoZSBwcm94eSBzZXJ2ZXIsCiAqIGFuZCB0aGVuIHRoZSBwcm94eSBzZXJ2ZXIgY29ubmVjdHMgdG8gdGhlIGRlc3RpbmF0aW9uIHRhcmdldCBhbmQgaXNzdWVzIHRoZQogKiBIVFRQIHJlcXVlc3QgZnJvbSB0aGUgcHJveHkgc2VydmVyLgogKgogKiBgaHR0cHM6YCByZXF1ZXN0cyBoYXZlIHRoZWlyIHNvY2tldCBjb25uZWN0aW9uIHVwZ3JhZGVkIHRvIFRMUyBvbmNlCiAqIHRoZSBjb25uZWN0aW9uIHRvIHRoZSBwcm94eSBzZXJ2ZXIgaGFzIGJlZW4gZXN0YWJsaXNoZWQuCiAqLwpjbGFzcyBIdHRwc1Byb3h5QWdlbnQgZXh0ZW5kcyBBZ2VudCB7CiAgc3RhdGljIF9faW5pdFN0YXRpYygpIHt0aGlzLnByb3RvY29scyA9IFsnaHR0cCcsICdodHRwcyddOyB9CgogIGNvbnN0cnVjdG9yKHByb3h5LCBvcHRzKSB7CiAgICBzdXBlcihvcHRzKTsKICAgIHRoaXMub3B0aW9ucyA9IHt9OwogICAgdGhpcy5wcm94eSA9IHR5cGVvZiBwcm94eSA9PT0gJ3N0cmluZycgPyBuZXcgVVJMKHByb3h5KSA6IHByb3h5OwogICAgdGhpcy5wcm94eUhlYWRlcnMgPSBfbnVsbGlzaENvYWxlc2NlJDEoX29wdGlvbmFsQ2hhaW4kMShbb3B0cywgJ29wdGlvbmFsQWNjZXNzJywgXzIgPT4gXzIuaGVhZGVyc10pLCAoKSA9PiAoIHt9KSk7CiAgICBkZWJ1ZygnQ3JlYXRpbmcgbmV3IEh0dHBzUHJveHlBZ2VudCBpbnN0YW5jZTogJW8nLCB0aGlzLnByb3h5LmhyZWYpOwoKICAgIC8vIFRyaW0gb2ZmIHRoZSBicmFja2V0cyBmcm9tIElQdjYgYWRkcmVzc2VzCiAgICBjb25zdCBob3N0ID0gKHRoaXMucHJveHkuaG9zdG5hbWUgfHwgdGhpcy5wcm94eS5ob3N0KS5yZXBsYWNlKC9eXFt8XF0kL2csICcnKTsKICAgIGNvbnN0IHBvcnQgPSB0aGlzLnByb3h5LnBvcnQgPyBwYXJzZUludCh0aGlzLnByb3h5LnBvcnQsIDEwKSA6IHRoaXMucHJveHkucHJvdG9jb2wgPT09ICdodHRwczonID8gNDQzIDogODA7CiAgICB0aGlzLmNvbm5lY3RPcHRzID0gewogICAgICAvLyBBdHRlbXB0IHRvIG5lZ290aWF0ZSBodHRwLzEuMSBmb3IgcHJveHkgc2VydmVycyB0aGF0IHN1cHBvcnQgaHR0cC8yCiAgICAgIEFMUE5Qcm90b2NvbHM6IFsnaHR0cC8xLjEnXSwKICAgICAgLi4uKG9wdHMgPyBvbWl0KG9wdHMsICdoZWFkZXJzJykgOiBudWxsKSwKICAgICAgaG9zdCwKICAgICAgcG9ydCwKICAgIH07CiAgfQoKICAvKioKICAgKiBDYWxsZWQgd2hlbiB0aGUgbm9kZS1jb3JlIEhUVFAgY2xpZW50IGxpYnJhcnkgaXMgY3JlYXRpbmcgYQogICAqIG5ldyBIVFRQIHJlcXVlc3QuCiAgICovCiAgYXN5bmMgY29ubmVjdChyZXEsIG9wdHMpIHsKICAgIGNvbnN0IHsgcHJveHkgfSA9IHRoaXM7CgogICAgaWYgKCFvcHRzLmhvc3QpIHsKICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignTm8gImhvc3QiIHByb3ZpZGVkJyk7CiAgICB9CgogICAgLy8gQ3JlYXRlIGEgc29ja2V0IGNvbm5lY3Rpb24gdG8gdGhlIHByb3h5IHNlcnZlci4KICAgIGxldCBzb2NrZXQ7CiAgICBpZiAocHJveHkucHJvdG9jb2wgPT09ICdodHRwczonKSB7CiAgICAgIGRlYnVnKCdDcmVhdGluZyBgdGxzLlNvY2tldGA6ICVvJywgdGhpcy5jb25uZWN0T3B0cyk7CiAgICAgIGNvbnN0IHNlcnZlcm5hbWUgPSB0aGlzLmNvbm5lY3RPcHRzLnNlcnZlcm5hbWUgfHwgdGhpcy5jb25uZWN0T3B0cy5ob3N0OwogICAgICBzb2NrZXQgPSB0bHMuY29ubmVjdCh7CiAgICAgICAgLi4udGhpcy5jb25uZWN0T3B0cywKICAgICAgICBzZXJ2ZXJuYW1lOiBzZXJ2ZXJuYW1lICYmIG5ldC5pc0lQKHNlcnZlcm5hbWUpID8gdW5kZWZpbmVkIDogc2VydmVybmFtZSwKICAgICAgfSk7CiAgICB9IGVsc2UgewogICAgICBkZWJ1ZygnQ3JlYXRpbmcgYG5ldC5Tb2NrZXRgOiAlbycsIHRoaXMuY29ubmVjdE9wdHMpOwogICAgICBzb2NrZXQgPSBuZXQuY29ubmVjdCh0aGlzLmNvbm5lY3RPcHRzKTsKICAgIH0KCiAgICBjb25zdCBoZWFkZXJzID0KICAgICAgdHlwZW9mIHRoaXMucHJveHlIZWFkZXJzID09PSAnZnVuY3Rpb24nID8gdGhpcy5wcm94eUhlYWRlcnMoKSA6IHsgLi4udGhpcy5wcm94eUhlYWRlcnMgfTsKICAgIGNvbnN0IGhvc3QgPSBuZXQuaXNJUHY2KG9wdHMuaG9zdCkgPyBgWyR7b3B0cy5ob3N0fV1gIDogb3B0cy5ob3N0OwogICAgbGV0IHBheWxvYWQgPSBgQ09OTkVDVCAke2hvc3R9OiR7b3B0cy5wb3J0fSBIVFRQLzEuMVxyXG5gOwoKICAgIC8vIEluamVjdCB0aGUgYFByb3h5LUF1dGhvcml6YXRpb25gIGhlYWRlciBpZiBuZWNlc3NhcnkuCiAgICBpZiAocHJveHkudXNlcm5hbWUgfHwgcHJveHkucGFzc3dvcmQpIHsKICAgICAgY29uc3QgYXV0aCA9IGAke2RlY29kZVVSSUNvbXBvbmVudChwcm94eS51c2VybmFtZSl9OiR7ZGVjb2RlVVJJQ29tcG9uZW50KHByb3h5LnBhc3N3b3JkKX1gOwogICAgICBoZWFkZXJzWydQcm94eS1BdXRob3JpemF0aW9uJ10gPSBgQmFzaWMgJHtCdWZmZXIuZnJvbShhdXRoKS50b1N0cmluZygnYmFzZTY0Jyl9YDsKICAgIH0KCiAgICBoZWFkZXJzLkhvc3QgPSBgJHtob3N0fToke29wdHMucG9ydH1gOwoKICAgIGlmICghaGVhZGVyc1snUHJveHktQ29ubmVjdGlvbiddKSB7CiAgICAgIGhlYWRlcnNbJ1Byb3h5LUNvbm5lY3Rpb24nXSA9IHRoaXMua2VlcEFsaXZlID8gJ0tlZXAtQWxpdmUnIDogJ2Nsb3NlJzsKICAgIH0KICAgIGZvciAoY29uc3QgbmFtZSBvZiBPYmplY3Qua2V5cyhoZWFkZXJzKSkgewogICAgICBwYXlsb2FkICs9IGAke25hbWV9OiAke2hlYWRlcnNbbmFtZV19XHJcbmA7CiAgICB9CgogICAgY29uc3QgcHJveHlSZXNwb25zZVByb21pc2UgPSBwYXJzZVByb3h5UmVzcG9uc2Uoc29ja2V0KTsKCiAgICBzb2NrZXQud3JpdGUoYCR7cGF5bG9hZH1cclxuYCk7CgogICAgY29uc3QgeyBjb25uZWN0LCBidWZmZXJlZCB9ID0gYXdhaXQgcHJveHlSZXNwb25zZVByb21pc2U7CiAgICByZXEuZW1pdCgncHJveHlDb25uZWN0JywgY29ubmVjdCk7CiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L2Jhbi10cy1jb21tZW50CiAgICAvLyBAdHMtaWdub3JlIE5vdCBFdmVudEVtaXR0ZXIgaW4gTm9kZSB0eXBlcwogICAgdGhpcy5lbWl0KCdwcm94eUNvbm5lY3QnLCBjb25uZWN0LCByZXEpOwoKICAgIGlmIChjb25uZWN0LnN0YXR1c0NvZGUgPT09IDIwMCkgewogICAgICByZXEub25jZSgnc29ja2V0JywgcmVzdW1lKTsKCiAgICAgIGlmIChvcHRzLnNlY3VyZUVuZHBvaW50KSB7CiAgICAgICAgLy8gVGhlIHByb3h5IGlzIGNvbm5lY3RpbmcgdG8gYSBUTFMgc2VydmVyLCBzbyB1cGdyYWRlCiAgICAgICAgLy8gdGhpcyBzb2NrZXQgY29ubmVjdGlvbiB0byBhIFRMUyBjb25uZWN0aW9uLgogICAgICAgIGRlYnVnKCdVcGdyYWRpbmcgc29ja2V0IGNvbm5lY3Rpb24gdG8gVExTJyk7CiAgICAgICAgY29uc3Qgc2VydmVybmFtZSA9IG9wdHMuc2VydmVybmFtZSB8fCBvcHRzLmhvc3Q7CiAgICAgICAgcmV0dXJuIHRscy5jb25uZWN0KHsKICAgICAgICAgIC4uLm9taXQob3B0cywgJ2hvc3QnLCAncGF0aCcsICdwb3J0JyksCiAgICAgICAgICBzb2NrZXQsCiAgICAgICAgICBzZXJ2ZXJuYW1lOiBuZXQuaXNJUChzZXJ2ZXJuYW1lKSA/IHVuZGVmaW5lZCA6IHNlcnZlcm5hbWUsCiAgICAgICAgfSk7CiAgICAgIH0KCiAgICAgIHJldHVybiBzb2NrZXQ7CiAgICB9CgogICAgLy8gU29tZSBvdGhlciBzdGF0dXMgY29kZSB0aGF0J3Mgbm90IDIwMC4uLiBuZWVkIHRvIHJlLXBsYXkgdGhlIEhUVFAKICAgIC8vIGhlYWRlciAiZGF0YSIgZXZlbnRzIG9udG8gdGhlIHNvY2tldCBvbmNlIHRoZSBIVFRQIG1hY2hpbmVyeSBpcwogICAgLy8gYXR0YWNoZWQgc28gdGhhdCB0aGUgbm9kZSBjb3JlIGBodHRwYCBjYW4gcGFyc2UgYW5kIGhhbmRsZSB0aGUKICAgIC8vIGVycm9yIHN0YXR1cyBjb2RlLgoKICAgIC8vIENsb3NlIHRoZSBvcmlnaW5hbCBzb2NrZXQsIGFuZCBhIG5ldyAiZmFrZSIgc29ja2V0IGlzIHJldHVybmVkCiAgICAvLyBpbnN0ZWFkLCBzbyB0aGF0IHRoZSBwcm94eSBkb2Vzbid0IGdldCB0aGUgSFRUUCByZXF1ZXN0CiAgICAvLyB3cml0dGVuIHRvIGl0ICh3aGljaCBtYXkgY29udGFpbiBgQXV0aG9yaXphdGlvbmAgaGVhZGVycyBvciBvdGhlcgogICAgLy8gc2Vuc2l0aXZlIGRhdGEpLgogICAgLy8KICAgIC8vIFNlZTogaHR0cHM6Ly9oYWNrZXJvbmUuY29tL3JlcG9ydHMvNTQxNTAyCiAgICBzb2NrZXQuZGVzdHJveSgpOwoKICAgIGNvbnN0IGZha2VTb2NrZXQgPSBuZXcgbmV0LlNvY2tldCh7IHdyaXRhYmxlOiBmYWxzZSB9KTsKICAgIGZha2VTb2NrZXQucmVhZGFibGUgPSB0cnVlOwoKICAgIC8vIE5lZWQgdG8gd2FpdCBmb3IgdGhlICJzb2NrZXQiIGV2ZW50IHRvIHJlLXBsYXkgdGhlICJkYXRhIiBldmVudHMuCiAgICByZXEub25jZSgnc29ja2V0JywgKHMpID0+IHsKICAgICAgZGVidWcoJ1JlcGxheWluZyBwcm94eSBidWZmZXIgZm9yIGZhaWxlZCByZXF1ZXN0Jyk7CiAgICAgIC8vIFJlcGxheSB0aGUgImJ1ZmZlcmVkIiBCdWZmZXIgb250byB0aGUgZmFrZSBgc29ja2V0YCwgc2luY2UgYXQKICAgICAgLy8gdGhpcyBwb2ludCB0aGUgSFRUUCBtb2R1bGUgbWFjaGluZXJ5IGhhcyBiZWVuIGhvb2tlZCB1cCBmb3IKICAgICAgLy8gdGhlIHVzZXIuCiAgICAgIHMucHVzaChidWZmZXJlZCk7CiAgICAgIHMucHVzaChudWxsKTsKICAgIH0pOwoKICAgIHJldHVybiBmYWtlU29ja2V0OwogIH0KfSBIdHRwc1Byb3h5QWdlbnQuX19pbml0U3RhdGljKCk7CgpmdW5jdGlvbiByZXN1bWUoc29ja2V0KSB7CiAgc29ja2V0LnJlc3VtZSgpOwp9CgpmdW5jdGlvbiBvbWl0KAogIG9iaiwKICAuLi5rZXlzCikKCiB7CiAgY29uc3QgcmV0ID0ge30KCjsKICBsZXQga2V5OwogIGZvciAoa2V5IGluIG9iaikgewogICAgaWYgKCFrZXlzLmluY2x1ZGVzKGtleSkpIHsKICAgICAgcmV0W2tleV0gPSBvYmpba2V5XTsKICAgIH0KICB9CiAgcmV0dXJuIHJldDsKfQoKZnVuY3Rpb24gX251bGxpc2hDb2FsZXNjZShsaHMsIHJoc0ZuKSB7IGlmIChsaHMgIT0gbnVsbCkgeyByZXR1cm4gbGhzOyB9IGVsc2UgeyByZXR1cm4gcmhzRm4oKTsgfSB9Ci8vIEVzdGltYXRlZCBtYXhpbXVtIHNpemUgZm9yIHJlYXNvbmFibGUgc3RhbmRhbG9uZSBldmVudApjb25zdCBHWklQX1RIUkVTSE9MRCA9IDEwMjQgKiAzMjsKCi8qKgogKiBHZXRzIGEgc3RyZWFtIGZyb20gYSBVaW50OEFycmF5IG9yIHN0cmluZwogKiBSZWFkYWJsZS5mcm9tIGlzIGlkZWFsIGJ1dCB3YXMgYWRkZWQgaW4gbm9kZS5qcyB2MTIuMy4wIGFuZCB2MTAuMTcuMAogKi8KZnVuY3Rpb24gc3RyZWFtRnJvbUJvZHkoYm9keSkgewogIHJldHVybiBuZXcgUmVhZGFibGUoewogICAgcmVhZCgpIHsKICAgICAgdGhpcy5wdXNoKGJvZHkpOwogICAgICB0aGlzLnB1c2gobnVsbCk7CiAgICB9LAogIH0pOwp9CgovKioKICogQ3JlYXRlcyBhIFRyYW5zcG9ydCB0aGF0IHVzZXMgbmF0aXZlIHRoZSBuYXRpdmUgJ2h0dHAnIGFuZCAnaHR0cHMnIG1vZHVsZXMgdG8gc2VuZCBldmVudHMgdG8gU2VudHJ5LgogKi8KZnVuY3Rpb24gbWFrZU5vZGVUcmFuc3BvcnQob3B0aW9ucykgewogIGxldCB1cmxTZWdtZW50czsKCiAgdHJ5IHsKICAgIHVybFNlZ21lbnRzID0gbmV3IFVSTChvcHRpb25zLnVybCk7CiAgfSBjYXRjaCAoZSkgewogICAgY29uc29sZVNhbmRib3goKCkgPT4gewogICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29uc29sZQogICAgICBjb25zb2xlLndhcm4oCiAgICAgICAgJ1tAc2VudHJ5L25vZGVdOiBJbnZhbGlkIGRzbiBvciB0dW5uZWwgb3B0aW9uLCB3aWxsIG5vdCBzZW5kIGFueSBldmVudHMuIFRoZSB0dW5uZWwgb3B0aW9uIG11c3QgYmUgYSBmdWxsIFVSTCB3aGVuIHVzZWQuJywKICAgICAgKTsKICAgIH0pOwogICAgcmV0dXJuIGNyZWF0ZVRyYW5zcG9ydChvcHRpb25zLCAoKSA9PiBQcm9taXNlLnJlc29sdmUoe30pKTsKICB9CgogIGNvbnN0IGlzSHR0cHMgPSB1cmxTZWdtZW50cy5wcm90b2NvbCA9PT0gJ2h0dHBzOic7CgogIC8vIFByb3h5IHByaW9yaXRpemF0aW9uOiBodHRwID0+IGBvcHRpb25zLnByb3h5YCB8IGBwcm9jZXNzLmVudi5odHRwX3Byb3h5YAogIC8vIFByb3h5IHByaW9yaXRpemF0aW9uOiBodHRwcyA9PiBgb3B0aW9ucy5wcm94eWAgfCBgcHJvY2Vzcy5lbnYuaHR0cHNfcHJveHlgIHwgYHByb2Nlc3MuZW52Lmh0dHBfcHJveHlgCiAgY29uc3QgcHJveHkgPSBhcHBseU5vUHJveHlPcHRpb24oCiAgICB1cmxTZWdtZW50cywKICAgIG9wdGlvbnMucHJveHkgfHwgKGlzSHR0cHMgPyBwcm9jZXNzLmVudi5odHRwc19wcm94eSA6IHVuZGVmaW5lZCkgfHwgcHJvY2Vzcy5lbnYuaHR0cF9wcm94eSwKICApOwoKICBjb25zdCBuYXRpdmVIdHRwTW9kdWxlID0gaXNIdHRwcyA/IGh0dHBzIDogaHR0cCQxOwogIGNvbnN0IGtlZXBBbGl2ZSA9IG9wdGlvbnMua2VlcEFsaXZlID09PSB1bmRlZmluZWQgPyBmYWxzZSA6IG9wdGlvbnMua2VlcEFsaXZlOwoKICAvLyBUT0RPKHY3KTogRXZhbHVhdGUgaWYgd2UgY2FuIHNldCBrZWVwQWxpdmUgdG8gdHJ1ZS4gVGhpcyB3b3VsZCBpbnZvbHZlIHRlc3RpbmcgZm9yIG1lbW9yeSBsZWFrcyBpbiBvbGRlciBub2RlCiAgLy8gdmVyc2lvbnMoPj0gOCkgYXMgdGhleSBoYWQgbWVtb3J5IGxlYWtzIHdoZW4gdXNpbmcgaXQ6ICMyNTU1CiAgY29uc3QgYWdlbnQgPSBwcm94eQogICAgPyAobmV3IEh0dHBzUHJveHlBZ2VudChwcm94eSkgKQogICAgOiBuZXcgbmF0aXZlSHR0cE1vZHVsZS5BZ2VudCh7IGtlZXBBbGl2ZSwgbWF4U29ja2V0czogMzAsIHRpbWVvdXQ6IDIwMDAgfSk7CgogIC8vIFRoaXMgZW5zdXJlcyB3ZSBkbyBub3QgZ2VuZXJhdGUgYW55IHNwYW5zIGluIE9wZW5UZWxlbWV0cnkgZm9yIHRoZSB0cmFuc3BvcnQKICByZXR1cm4gc3VwcHJlc3NUcmFjaW5nKCgpID0+IHsKICAgIGNvbnN0IHJlcXVlc3RFeGVjdXRvciA9IGNyZWF0ZVJlcXVlc3RFeGVjdXRvcihvcHRpb25zLCBfbnVsbGlzaENvYWxlc2NlKG9wdGlvbnMuaHR0cE1vZHVsZSwgKCkgPT4gKCBuYXRpdmVIdHRwTW9kdWxlKSksIGFnZW50KTsKICAgIHJldHVybiBjcmVhdGVUcmFuc3BvcnQob3B0aW9ucywgcmVxdWVzdEV4ZWN1dG9yKTsKICB9KTsKfQoKLyoqCiAqIEhvbm9ycyB0aGUgYG5vX3Byb3h5YCBlbnYgdmFyaWFibGUgd2l0aCB0aGUgaGlnaGVzdCBwcmlvcml0eSB0byBhbGxvdyBmb3IgaG9zdHMgZXhjbHVzaW9uLgogKgogKiBAcGFyYW0gdHJhbnNwb3J0VXJsIFRoZSBVUkwgdGhlIHRyYW5zcG9ydCBpbnRlbmRzIHRvIHNlbmQgZXZlbnRzIHRvLgogKiBAcGFyYW0gcHJveHkgVGhlIGNsaWVudCBjb25maWd1cmVkIHByb3h5LgogKiBAcmV0dXJucyBBIHByb3h5IHRoZSB0cmFuc3BvcnQgc2hvdWxkIHVzZS4KICovCmZ1bmN0aW9uIGFwcGx5Tm9Qcm94eU9wdGlvbih0cmFuc3BvcnRVcmxTZWdtZW50cywgcHJveHkpIHsKICBjb25zdCB7IG5vX3Byb3h5IH0gPSBwcm9jZXNzLmVudjsKCiAgY29uc3QgdXJsSXNFeGVtcHRGcm9tUHJveHkgPQogICAgbm9fcHJveHkgJiYKICAgIG5vX3Byb3h5CiAgICAgIC5zcGxpdCgnLCcpCiAgICAgIC5zb21lKAogICAgICAgIGV4ZW1wdGlvbiA9PiB0cmFuc3BvcnRVcmxTZWdtZW50cy5ob3N0LmVuZHNXaXRoKGV4ZW1wdGlvbikgfHwgdHJhbnNwb3J0VXJsU2VnbWVudHMuaG9zdG5hbWUuZW5kc1dpdGgoZXhlbXB0aW9uKSwKICAgICAgKTsKCiAgaWYgKHVybElzRXhlbXB0RnJvbVByb3h5KSB7CiAgICByZXR1cm4gdW5kZWZpbmVkOwogIH0gZWxzZSB7CiAgICByZXR1cm4gcHJveHk7CiAgfQp9CgovKioKICogQ3JlYXRlcyBhIFJlcXVlc3RFeGVjdXRvciB0byBiZSB1c2VkIHdpdGggYGNyZWF0ZVRyYW5zcG9ydGAuCiAqLwpmdW5jdGlvbiBjcmVhdGVSZXF1ZXN0RXhlY3V0b3IoCiAgb3B0aW9ucywKICBodHRwTW9kdWxlLAogIGFnZW50LAopIHsKICBjb25zdCB7IGhvc3RuYW1lLCBwYXRobmFtZSwgcG9ydCwgcHJvdG9jb2wsIHNlYXJjaCB9ID0gbmV3IFVSTChvcHRpb25zLnVybCk7CiAgcmV0dXJuIGZ1bmN0aW9uIG1ha2VSZXF1ZXN0KHJlcXVlc3QpIHsKICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7CiAgICAgIGxldCBib2R5ID0gc3RyZWFtRnJvbUJvZHkocmVxdWVzdC5ib2R5KTsKCiAgICAgIGNvbnN0IGhlYWRlcnMgPSB7IC4uLm9wdGlvbnMuaGVhZGVycyB9OwoKICAgICAgaWYgKHJlcXVlc3QuYm9keS5sZW5ndGggPiBHWklQX1RIUkVTSE9MRCkgewogICAgICAgIGhlYWRlcnNbJ2NvbnRlbnQtZW5jb2RpbmcnXSA9ICdnemlwJzsKICAgICAgICBib2R5ID0gYm9keS5waXBlKGNyZWF0ZUd6aXAoKSk7CiAgICAgIH0KCiAgICAgIGNvbnN0IHJlcSA9IGh0dHBNb2R1bGUucmVxdWVzdCgKICAgICAgICB7CiAgICAgICAgICBtZXRob2Q6ICdQT1NUJywKICAgICAgICAgIGFnZW50LAogICAgICAgICAgaGVhZGVycywKICAgICAgICAgIGhvc3RuYW1lLAogICAgICAgICAgcGF0aDogYCR7cGF0aG5hbWV9JHtzZWFyY2h9YCwKICAgICAgICAgIHBvcnQsCiAgICAgICAgICBwcm90b2NvbCwKICAgICAgICAgIGNhOiBvcHRpb25zLmNhQ2VydHMsCiAgICAgICAgfSwKICAgICAgICByZXMgPT4gewogICAgICAgICAgcmVzLm9uKCdkYXRhJywgKCkgPT4gewogICAgICAgICAgICAvLyBEcmFpbiBzb2NrZXQKICAgICAgICAgIH0pOwoKICAgICAgICAgIHJlcy5vbignZW5kJywgKCkgPT4gewogICAgICAgICAgICAvLyBEcmFpbiBzb2NrZXQKICAgICAgICAgIH0pOwoKICAgICAgICAgIHJlcy5zZXRFbmNvZGluZygndXRmOCcpOwoKICAgICAgICAgIC8vICJLZXktdmFsdWUgcGFpcnMgb2YgaGVhZGVyIG5hbWVzIGFuZCB2YWx1ZXMuIEhlYWRlciBuYW1lcyBhcmUgbG93ZXItY2FzZWQuIgogICAgICAgICAgLy8gaHR0cHM6Ly9ub2RlanMub3JnL2FwaS9odHRwLmh0bWwjaHR0cF9tZXNzYWdlX2hlYWRlcnMKICAgICAgICAgIGNvbnN0IHJldHJ5QWZ0ZXJIZWFkZXIgPSBfbnVsbGlzaENvYWxlc2NlKHJlcy5oZWFkZXJzWydyZXRyeS1hZnRlciddLCAoKSA9PiAoIG51bGwpKTsKICAgICAgICAgIGNvbnN0IHJhdGVMaW1pdHNIZWFkZXIgPSBfbnVsbGlzaENvYWxlc2NlKHJlcy5oZWFkZXJzWyd4LXNlbnRyeS1yYXRlLWxpbWl0cyddLCAoKSA9PiAoIG51bGwpKTsKCiAgICAgICAgICByZXNvbHZlKHsKICAgICAgICAgICAgc3RhdHVzQ29kZTogcmVzLnN0YXR1c0NvZGUsCiAgICAgICAgICAgIGhlYWRlcnM6IHsKICAgICAgICAgICAgICAncmV0cnktYWZ0ZXInOiByZXRyeUFmdGVySGVhZGVyLAogICAgICAgICAgICAgICd4LXNlbnRyeS1yYXRlLWxpbWl0cyc6IEFycmF5LmlzQXJyYXkocmF0ZUxpbWl0c0hlYWRlcikgPyByYXRlTGltaXRzSGVhZGVyWzBdIDogcmF0ZUxpbWl0c0hlYWRlciwKICAgICAgICAgICAgfSwKICAgICAgICAgIH0pOwogICAgICAgIH0sCiAgICAgICk7CgogICAgICByZXEub24oJ2Vycm9yJywgcmVqZWN0KTsKICAgICAgYm9keS5waXBlKHJlcSk7CiAgICB9KTsKICB9Owp9CgovKiogbm9ybWFsaXplcyBXaW5kb3dzIHBhdGhzICovCmZ1bmN0aW9uIG5vcm1hbGl6ZVdpbmRvd3NQYXRoKHBhdGgpIHsKICByZXR1cm4gcGF0aAogICAgLnJlcGxhY2UoL15bQS1aXTovLCAnJykgLy8gcmVtb3ZlIFdpbmRvd3Mtc3R5bGUgcHJlZml4CiAgICAucmVwbGFjZSgvXFwvZywgJy8nKTsgLy8gcmVwbGFjZSBhbGwgYFxgIGluc3RhbmNlcyB3aXRoIGAvYAp9CgovKiogQ3JlYXRlcyBhIGZ1bmN0aW9uIHRoYXQgZ2V0cyB0aGUgbW9kdWxlIG5hbWUgZnJvbSBhIGZpbGVuYW1lICovCmZ1bmN0aW9uIGNyZWF0ZUdldE1vZHVsZUZyb21GaWxlbmFtZSgKICBiYXNlUGF0aCA9IHByb2Nlc3MuYXJndlsxXSA/IGRpcm5hbWUocHJvY2Vzcy5hcmd2WzFdKSA6IHByb2Nlc3MuY3dkKCksCiAgaXNXaW5kb3dzID0gc2VwID09PSAnXFwnLAopIHsKICBjb25zdCBub3JtYWxpemVkQmFzZSA9IGlzV2luZG93cyA/IG5vcm1hbGl6ZVdpbmRvd3NQYXRoKGJhc2VQYXRoKSA6IGJhc2VQYXRoOwoKICByZXR1cm4gKGZpbGVuYW1lKSA9PiB7CiAgICBpZiAoIWZpbGVuYW1lKSB7CiAgICAgIHJldHVybjsKICAgIH0KCiAgICBjb25zdCBub3JtYWxpemVkRmlsZW5hbWUgPSBpc1dpbmRvd3MgPyBub3JtYWxpemVXaW5kb3dzUGF0aChmaWxlbmFtZSkgOiBmaWxlbmFtZTsKCiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgcHJlZmVyLWNvbnN0CiAgICBsZXQgeyBkaXIsIGJhc2U6IGZpbGUsIGV4dCB9ID0gcG9zaXgucGFyc2Uobm9ybWFsaXplZEZpbGVuYW1lKTsKCiAgICBpZiAoZXh0ID09PSAnLmpzJyB8fCBleHQgPT09ICcubWpzJyB8fCBleHQgPT09ICcuY2pzJykgewogICAgICBmaWxlID0gZmlsZS5zbGljZSgwLCBleHQubGVuZ3RoICogLTEpOwogICAgfQoKICAgIGlmICghZGlyKSB7CiAgICAgIC8vIE5vIGRpcm5hbWUgd2hhdHNvZXZlcgogICAgICBkaXIgPSAnLic7CiAgICB9CgogICAgY29uc3QgbiA9IGRpci5sYXN0SW5kZXhPZignL25vZGVfbW9kdWxlcycpOwogICAgaWYgKG4gPiAtMSkgewogICAgICByZXR1cm4gYCR7ZGlyLnNsaWNlKG4gKyAxNCkucmVwbGFjZSgvXC8vZywgJy4nKX06JHtmaWxlfWA7CiAgICB9CgogICAgLy8gTGV0J3Mgc2VlIGlmIGl0J3MgYSBwYXJ0IG9mIHRoZSBtYWluIG1vZHVsZQogICAgLy8gVG8gYmUgYSBwYXJ0IG9mIG1haW4gbW9kdWxlLCBpdCBoYXMgdG8gc2hhcmUgdGhlIHNhbWUgYmFzZQogICAgaWYgKGRpci5zdGFydHNXaXRoKG5vcm1hbGl6ZWRCYXNlKSkgewogICAgICBsZXQgbW9kdWxlTmFtZSA9IGRpci5zbGljZShub3JtYWxpemVkQmFzZS5sZW5ndGggKyAxKS5yZXBsYWNlKC9cLy9nLCAnLicpOwoKICAgICAgaWYgKG1vZHVsZU5hbWUpIHsKICAgICAgICBtb2R1bGVOYW1lICs9ICc6JzsKICAgICAgfQogICAgICBtb2R1bGVOYW1lICs9IGZpbGU7CgogICAgICByZXR1cm4gbW9kdWxlTmFtZTsKICAgIH0KCiAgICByZXR1cm4gZmlsZTsKICB9Owp9CgpmdW5jdGlvbiBfb3B0aW9uYWxDaGFpbihvcHMpIHsgbGV0IGxhc3RBY2Nlc3NMSFMgPSB1bmRlZmluZWQ7IGxldCB2YWx1ZSA9IG9wc1swXTsgbGV0IGkgPSAxOyB3aGlsZSAoaSA8IG9wcy5sZW5ndGgpIHsgY29uc3Qgb3AgPSBvcHNbaV07IGNvbnN0IGZuID0gb3BzW2kgKyAxXTsgaSArPSAyOyBpZiAoKG9wID09PSAnb3B0aW9uYWxBY2Nlc3MnIHx8IG9wID09PSAnb3B0aW9uYWxDYWxsJykgJiYgdmFsdWUgPT0gbnVsbCkgeyByZXR1cm4gdW5kZWZpbmVkOyB9IGlmIChvcCA9PT0gJ2FjY2VzcycgfHwgb3AgPT09ICdvcHRpb25hbEFjY2VzcycpIHsgbGFzdEFjY2Vzc0xIUyA9IHZhbHVlOyB2YWx1ZSA9IGZuKHZhbHVlKTsgfSBlbHNlIGlmIChvcCA9PT0gJ2NhbGwnIHx8IG9wID09PSAnb3B0aW9uYWxDYWxsJykgeyB2YWx1ZSA9IGZuKCguLi5hcmdzKSA9PiB2YWx1ZS5jYWxsKGxhc3RBY2Nlc3NMSFMsIC4uLmFyZ3MpKTsgbGFzdEFjY2Vzc0xIUyA9IHVuZGVmaW5lZDsgfSB9IHJldHVybiB2YWx1ZTsgfQpjb25zdCBvcHRpb25zID0gd29ya2VyRGF0YTsKbGV0IHNlc3Npb247CmxldCBoYXNTZW50QW5yRXZlbnQgPSBmYWxzZTsKCmZ1bmN0aW9uIGxvZyhtc2cpIHsKICBpZiAob3B0aW9ucy5kZWJ1ZykgewogICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWNvbnNvbGUKICAgIGNvbnNvbGUubG9nKGBbQU5SIFdvcmtlcl0gJHttc2d9YCk7CiAgfQp9Cgpjb25zdCB1cmwgPSBnZXRFbnZlbG9wZUVuZHBvaW50V2l0aFVybEVuY29kZWRBdXRoKG9wdGlvbnMuZHNuLCBvcHRpb25zLnR1bm5lbCwgb3B0aW9ucy5zZGtNZXRhZGF0YS5zZGspOwpjb25zdCB0cmFuc3BvcnQgPSBtYWtlTm9kZVRyYW5zcG9ydCh7CiAgdXJsLAogIHJlY29yZERyb3BwZWRFdmVudDogKCkgPT4gewogICAgLy8KICB9LAp9KTsKCmFzeW5jIGZ1bmN0aW9uIHNlbmRBYm5vcm1hbFNlc3Npb24oKSB7CiAgLy8gb2Ygd2UgaGF2ZSBhbiBleGlzdGluZyBzZXNzaW9uIHBhc3NlZCBmcm9tIHRoZSBtYWluIHRocmVhZCwgc2VuZCBpdCBhcyBhYm5vcm1hbAogIGlmIChzZXNzaW9uKSB7CiAgICBsb2coJ1NlbmRpbmcgYWJub3JtYWwgc2Vzc2lvbicpOwogICAgdXBkYXRlU2Vzc2lvbihzZXNzaW9uLCB7IHN0YXR1czogJ2Fibm9ybWFsJywgYWJub3JtYWxfbWVjaGFuaXNtOiAnYW5yX2ZvcmVncm91bmQnIH0pOwoKICAgIGNvbnN0IGVudmVsb3BlID0gY3JlYXRlU2Vzc2lvbkVudmVsb3BlKHNlc3Npb24sIG9wdGlvbnMuZHNuLCBvcHRpb25zLnNka01ldGFkYXRhLCBvcHRpb25zLnR1bm5lbCk7CiAgICAvLyBMb2cgdGhlIGVudmVsb3BlIHNvIHRvIGFpZCBpbiB0ZXN0aW5nCiAgICBsb2coSlNPTi5zdHJpbmdpZnkoZW52ZWxvcGUpKTsKCiAgICBhd2FpdCB0cmFuc3BvcnQuc2VuZChlbnZlbG9wZSk7CgogICAgdHJ5IHsKICAgICAgLy8gTm90aWZ5IHRoZSBtYWluIHByb2Nlc3MgdGhhdCB0aGUgc2Vzc2lvbiBoYXMgZW5kZWQgc28gdGhlIHNlc3Npb24gY2FuIGJlIGNsZWFyZWQgZnJvbSB0aGUgc2NvcGUKICAgICAgX29wdGlvbmFsQ2hhaW4oW3BhcmVudFBvcnQsICdvcHRpb25hbEFjY2VzcycsIF8yID0+IF8yLnBvc3RNZXNzYWdlLCAnY2FsbCcsIF8zID0+IF8zKCdzZXNzaW9uLWVuZGVkJyldKTsKICAgIH0gY2F0Y2ggKF8pIHsKICAgICAgLy8gaWdub3JlCiAgICB9CiAgfQp9Cgpsb2coJ1N0YXJ0ZWQnKTsKCmZ1bmN0aW9uIHByZXBhcmVTdGFja0ZyYW1lcyhzdGFja0ZyYW1lcykgewogIGlmICghc3RhY2tGcmFtZXMpIHsKICAgIHJldHVybiB1bmRlZmluZWQ7CiAgfQoKICAvLyBTdHJpcCBTZW50cnkgZnJhbWVzIGFuZCByZXZlcnNlIHRoZSBzdGFjayBmcmFtZXMgc28gdGhleSBhcmUgaW4gdGhlIGNvcnJlY3Qgb3JkZXIKICBjb25zdCBzdHJpcHBlZEZyYW1lcyA9IHN0cmlwU2VudHJ5RnJhbWVzQW5kUmV2ZXJzZShzdGFja0ZyYW1lcyk7CgogIC8vIElmIHdlIGhhdmUgYW4gYXBwIHJvb3QgcGF0aCwgcmV3cml0ZSB0aGUgZmlsZW5hbWVzIHRvIGJlIHJlbGF0aXZlIHRvIHRoZSBhcHAgcm9vdAogIGlmIChvcHRpb25zLmFwcFJvb3RQYXRoKSB7CiAgICBmb3IgKGNvbnN0IGZyYW1lIG9mIHN0cmlwcGVkRnJhbWVzKSB7CiAgICAgIGlmICghZnJhbWUuZmlsZW5hbWUpIHsKICAgICAgICBjb250aW51ZTsKICAgICAgfQoKICAgICAgZnJhbWUuZmlsZW5hbWUgPSBub3JtYWxpemVVcmxUb0Jhc2UoZnJhbWUuZmlsZW5hbWUsIG9wdGlvbnMuYXBwUm9vdFBhdGgpOwogICAgfQogIH0KCiAgcmV0dXJuIHN0cmlwcGVkRnJhbWVzOwp9CgpmdW5jdGlvbiBhcHBseVNjb3BlVG9FdmVudChldmVudCwgc2NvcGUpIHsKICBhcHBseVNjb3BlRGF0YVRvRXZlbnQoZXZlbnQsIHNjb3BlKTsKCiAgaWYgKCFfb3B0aW9uYWxDaGFpbihbZXZlbnQsICdhY2Nlc3MnLCBfNCA9PiBfNC5jb250ZXh0cywgJ29wdGlvbmFsQWNjZXNzJywgXzUgPT4gXzUudHJhY2VdKSkgewogICAgY29uc3QgeyB0cmFjZUlkLCBzcGFuSWQsIHBhcmVudFNwYW5JZCB9ID0gc2NvcGUucHJvcGFnYXRpb25Db250ZXh0OwogICAgZXZlbnQuY29udGV4dHMgPSB7CiAgICAgIHRyYWNlOiB7CiAgICAgICAgdHJhY2VfaWQ6IHRyYWNlSWQsCiAgICAgICAgc3Bhbl9pZDogc3BhbklkLAogICAgICAgIHBhcmVudF9zcGFuX2lkOiBwYXJlbnRTcGFuSWQsCiAgICAgIH0sCiAgICAgIC4uLmV2ZW50LmNvbnRleHRzLAogICAgfTsKICB9Cn0KCmFzeW5jIGZ1bmN0aW9uIHNlbmRBbnJFdmVudChmcmFtZXMsIHNjb3BlKSB7CiAgaWYgKGhhc1NlbnRBbnJFdmVudCkgewogICAgcmV0dXJuOwogIH0KCiAgaGFzU2VudEFuckV2ZW50ID0gdHJ1ZTsKCiAgYXdhaXQgc2VuZEFibm9ybWFsU2Vzc2lvbigpOwoKICBsb2coJ1NlbmRpbmcgZXZlbnQnKTsKCiAgY29uc3QgZXZlbnQgPSB7CiAgICBldmVudF9pZDogdXVpZDQoKSwKICAgIGNvbnRleHRzOiBvcHRpb25zLmNvbnRleHRzLAogICAgcmVsZWFzZTogb3B0aW9ucy5yZWxlYXNlLAogICAgZW52aXJvbm1lbnQ6IG9wdGlvbnMuZW52aXJvbm1lbnQsCiAgICBkaXN0OiBvcHRpb25zLmRpc3QsCiAgICBwbGF0Zm9ybTogJ25vZGUnLAogICAgbGV2ZWw6ICdlcnJvcicsCiAgICBleGNlcHRpb246IHsKICAgICAgdmFsdWVzOiBbCiAgICAgICAgewogICAgICAgICAgdHlwZTogJ0FwcGxpY2F0aW9uTm90UmVzcG9uZGluZycsCiAgICAgICAgICB2YWx1ZTogYEFwcGxpY2F0aW9uIE5vdCBSZXNwb25kaW5nIGZvciBhdCBsZWFzdCAke29wdGlvbnMuYW5yVGhyZXNob2xkfSBtc2AsCiAgICAgICAgICBzdGFja3RyYWNlOiB7IGZyYW1lczogcHJlcGFyZVN0YWNrRnJhbWVzKGZyYW1lcykgfSwKICAgICAgICAgIC8vIFRoaXMgZW5zdXJlcyB0aGUgVUkgZG9lc24ndCBzYXkgJ0NyYXNoZWQgaW4nIGZvciB0aGUgc3RhY2sgdHJhY2UKICAgICAgICAgIG1lY2hhbmlzbTogeyB0eXBlOiAnQU5SJyB9LAogICAgICAgIH0sCiAgICAgIF0sCiAgICB9LAogICAgdGFnczogb3B0aW9ucy5zdGF0aWNUYWdzLAogIH07CgogIGlmIChzY29wZSkgewogICAgYXBwbHlTY29wZVRvRXZlbnQoZXZlbnQsIHNjb3BlKTsKICB9CgogIGNvbnN0IGVudmVsb3BlID0gY3JlYXRlRXZlbnRFbnZlbG9wZShldmVudCwgb3B0aW9ucy5kc24sIG9wdGlvbnMuc2RrTWV0YWRhdGEsIG9wdGlvbnMudHVubmVsKTsKICAvLyBMb2cgdGhlIGVudmVsb3BlIHRvIGFpZCBpbiB0ZXN0aW5nCiAgbG9nKEpTT04uc3RyaW5naWZ5KGVudmVsb3BlKSk7CgogIGF3YWl0IHRyYW5zcG9ydC5zZW5kKGVudmVsb3BlKTsKICBhd2FpdCB0cmFuc3BvcnQuZmx1c2goMjAwMCk7CgogIC8vIERlbGF5IGZvciA1IHNlY29uZHMgc28gdGhhdCBzdGRpbyBjYW4gZmx1c2ggaWYgdGhlIG1haW4gZXZlbnQgbG9vcCBldmVyIHJlc3RhcnRzLgogIC8vIFRoaXMgaXMgbWFpbmx5IGZvciB0aGUgYmVuZWZpdCBvZiBsb2dnaW5nIG9yIGRlYnVnZ2luZy4KICBzZXRUaW1lb3V0KCgpID0+IHsKICAgIHByb2Nlc3MuZXhpdCgwKTsKICB9LCA1MDAwKTsKfQoKbGV0IGRlYnVnZ2VyUGF1c2U7CgppZiAob3B0aW9ucy5jYXB0dXJlU3RhY2tUcmFjZSkgewogIGxvZygnQ29ubmVjdGluZyB0byBkZWJ1Z2dlcicpOwoKICBjb25zdCBzZXNzaW9uID0gbmV3IFNlc3Npb24oKTsKICBzZXNzaW9uLmNvbm5lY3RUb01haW5UaHJlYWQoKTsKCiAgbG9nKCdDb25uZWN0ZWQgdG8gZGVidWdnZXInKTsKCiAgLy8gQ29sbGVjdCBzY3JpcHRJZCAtPiB1cmwgbWFwIHNvIHdlIGNhbiBsb29rIHVwIHRoZSBmaWxlbmFtZXMgbGF0ZXIKICBjb25zdCBzY3JpcHRzID0gbmV3IE1hcCgpOwoKICBzZXNzaW9uLm9uKCdEZWJ1Z2dlci5zY3JpcHRQYXJzZWQnLCBldmVudCA9PiB7CiAgICBzY3JpcHRzLnNldChldmVudC5wYXJhbXMuc2NyaXB0SWQsIGV2ZW50LnBhcmFtcy51cmwpOwogIH0pOwoKICBzZXNzaW9uLm9uKCdEZWJ1Z2dlci5wYXVzZWQnLCBldmVudCA9PiB7CiAgICBpZiAoZXZlbnQucGFyYW1zLnJlYXNvbiAhPT0gJ290aGVyJykgewogICAgICByZXR1cm47CiAgICB9CgogICAgdHJ5IHsKICAgICAgbG9nKCdEZWJ1Z2dlciBwYXVzZWQnKTsKCiAgICAgIC8vIGNvcHkgdGhlIGZyYW1lcwogICAgICBjb25zdCBjYWxsRnJhbWVzID0gWy4uLmV2ZW50LnBhcmFtcy5jYWxsRnJhbWVzXTsKCiAgICAgIGNvbnN0IGdldE1vZHVsZU5hbWUgPSBvcHRpb25zLmFwcFJvb3RQYXRoID8gY3JlYXRlR2V0TW9kdWxlRnJvbUZpbGVuYW1lKG9wdGlvbnMuYXBwUm9vdFBhdGgpIDogKCkgPT4gdW5kZWZpbmVkOwogICAgICBjb25zdCBzdGFja0ZyYW1lcyA9IGNhbGxGcmFtZXMubWFwKGZyYW1lID0+CiAgICAgICAgY2FsbEZyYW1lVG9TdGFja0ZyYW1lKGZyYW1lLCBzY3JpcHRzLmdldChmcmFtZS5sb2NhdGlvbi5zY3JpcHRJZCksIGdldE1vZHVsZU5hbWUpLAogICAgICApOwoKICAgICAgLy8gUnVudGltZS5ldmFsdWF0ZSBtYXkgbmV2ZXIgcmV0dXJuIGlmIHRoZSBldmVudCBsb29wIGlzIGJsb2NrZWQgaW5kZWZpbml0ZWx5CiAgICAgIC8vIEluIHRoYXQgY2FzZSwgd2Ugd2FudCB0byBzZW5kIHRoZSBldmVudCBhbnl3YXkKICAgICAgY29uc3QgZ2V0U2NvcGVUaW1lb3V0ID0gc2V0VGltZW91dCgoKSA9PiB7CiAgICAgICAgc2VuZEFuckV2ZW50KHN0YWNrRnJhbWVzKS50aGVuKG51bGwsICgpID0+IHsKICAgICAgICAgIGxvZygnU2VuZGluZyBBTlIgZXZlbnQgZmFpbGVkLicpOwogICAgICAgIH0pOwogICAgICB9LCA1MDAwKTsKCiAgICAgIC8vIEV2YWx1YXRlIGEgc2NyaXB0IGluIHRoZSBjdXJyZW50bHkgcGF1c2VkIGNvbnRleHQKICAgICAgc2Vzc2lvbi5wb3N0KAogICAgICAgICdSdW50aW1lLmV2YWx1YXRlJywKICAgICAgICB7CiAgICAgICAgICAvLyBHcmFiIHRoZSB0cmFjZSBjb250ZXh0IGZyb20gdGhlIGN1cnJlbnQgc2NvcGUKICAgICAgICAgIGV4cHJlc3Npb246ICdnbG9iYWwuX19TRU5UUllfR0VUX1NDT1BFU19fKCk7JywKICAgICAgICAgIC8vIERvbid0IHJlLXRyaWdnZXIgdGhlIGRlYnVnZ2VyIGlmIHRoaXMgY2F1c2VzIGFuIGVycm9yCiAgICAgICAgICBzaWxlbnQ6IHRydWUsCiAgICAgICAgICAvLyBTZXJpYWxpemUgdGhlIHJlc3VsdCB0byBqc29uIG90aGVyd2lzZSBvbmx5IHByaW1pdGl2ZXMgYXJlIHN1cHBvcnRlZAogICAgICAgICAgcmV0dXJuQnlWYWx1ZTogdHJ1ZSwKICAgICAgICB9LAogICAgICAgIChlcnIsIHBhcmFtKSA9PiB7CiAgICAgICAgICBpZiAoZXJyKSB7CiAgICAgICAgICAgIGxvZyhgRXJyb3IgZXhlY3V0aW5nIHNjcmlwdDogJyR7ZXJyLm1lc3NhZ2V9J2ApOwogICAgICAgICAgfQoKICAgICAgICAgIGNsZWFyVGltZW91dChnZXRTY29wZVRpbWVvdXQpOwoKICAgICAgICAgIGNvbnN0IHNjb3BlcyA9IHBhcmFtICYmIHBhcmFtLnJlc3VsdCA/IChwYXJhbS5yZXN1bHQudmFsdWUgKSA6IHVuZGVmaW5lZDsKCiAgICAgICAgICBzZXNzaW9uLnBvc3QoJ0RlYnVnZ2VyLnJlc3VtZScpOwogICAgICAgICAgc2Vzc2lvbi5wb3N0KCdEZWJ1Z2dlci5kaXNhYmxlJyk7CgogICAgICAgICAgc2VuZEFuckV2ZW50KHN0YWNrRnJhbWVzLCBzY29wZXMpLnRoZW4obnVsbCwgKCkgPT4gewogICAgICAgICAgICBsb2coJ1NlbmRpbmcgQU5SIGV2ZW50IGZhaWxlZC4nKTsKICAgICAgICAgIH0pOwogICAgICAgIH0sCiAgICAgICk7CiAgICB9IGNhdGNoIChlKSB7CiAgICAgIHNlc3Npb24ucG9zdCgnRGVidWdnZXIucmVzdW1lJyk7CiAgICAgIHNlc3Npb24ucG9zdCgnRGVidWdnZXIuZGlzYWJsZScpOwogICAgICB0aHJvdyBlOwogICAgfQogIH0pOwoKICBkZWJ1Z2dlclBhdXNlID0gKCkgPT4gewogICAgdHJ5IHsKICAgICAgc2Vzc2lvbi5wb3N0KCdEZWJ1Z2dlci5lbmFibGUnLCAoKSA9PiB7CiAgICAgICAgc2Vzc2lvbi5wb3N0KCdEZWJ1Z2dlci5wYXVzZScpOwogICAgICB9KTsKICAgIH0gY2F0Y2ggKF8pIHsKICAgICAgLy8KICAgIH0KICB9Owp9CgpmdW5jdGlvbiBjcmVhdGVIclRpbWVyKCkgewogIC8vIFRPRE8gKHY4KTogV2UgY2FuIHVzZSBwcm9jZXNzLmhydGltZS5iaWdpbnQoKSBhZnRlciB3ZSBkcm9wIG5vZGUgdjgKICBsZXQgbGFzdFBvbGwgPSBwcm9jZXNzLmhydGltZSgpOwoKICByZXR1cm4gewogICAgZ2V0VGltZU1zOiAoKSA9PiB7CiAgICAgIGNvbnN0IFtzZWNvbmRzLCBuYW5vU2Vjb25kc10gPSBwcm9jZXNzLmhydGltZShsYXN0UG9sbCk7CiAgICAgIHJldHVybiBNYXRoLmZsb29yKHNlY29uZHMgKiAxZTMgKyBuYW5vU2Vjb25kcyAvIDFlNik7CiAgICB9LAogICAgcmVzZXQ6ICgpID0+IHsKICAgICAgbGFzdFBvbGwgPSBwcm9jZXNzLmhydGltZSgpOwogICAgfSwKICB9Owp9CgpmdW5jdGlvbiB3YXRjaGRvZ1RpbWVvdXQoKSB7CiAgbG9nKCdXYXRjaGRvZyB0aW1lb3V0Jyk7CgogIGlmIChkZWJ1Z2dlclBhdXNlKSB7CiAgICBsb2coJ1BhdXNpbmcgZGVidWdnZXIgdG8gY2FwdHVyZSBzdGFjayB0cmFjZScpOwogICAgZGVidWdnZXJQYXVzZSgpOwogIH0gZWxzZSB7CiAgICBsb2coJ0NhcHR1cmluZyBldmVudCB3aXRob3V0IGEgc3RhY2sgdHJhY2UnKTsKICAgIHNlbmRBbnJFdmVudCgpLnRoZW4obnVsbCwgKCkgPT4gewogICAgICBsb2coJ1NlbmRpbmcgQU5SIGV2ZW50IGZhaWxlZCBvbiB3YXRjaGRvZyB0aW1lb3V0LicpOwogICAgfSk7CiAgfQp9Cgpjb25zdCB7IHBvbGwgfSA9IHdhdGNoZG9nVGltZXIoY3JlYXRlSHJUaW1lciwgb3B0aW9ucy5wb2xsSW50ZXJ2YWwsIG9wdGlvbnMuYW5yVGhyZXNob2xkLCB3YXRjaGRvZ1RpbWVvdXQpOwoKX29wdGlvbmFsQ2hhaW4oW3BhcmVudFBvcnQsICdvcHRpb25hbEFjY2VzcycsIF82ID0+IF82Lm9uLCAnY2FsbCcsIF83ID0+IF83KCdtZXNzYWdlJywgKG1zZykgPT4gewogIGlmIChtc2cuc2Vzc2lvbikgewogICAgc2Vzc2lvbiA9IG1ha2VTZXNzaW9uKG1zZy5zZXNzaW9uKTsKICB9CgogIHBvbGwoKTsKfSldKTs=';
1795
+ const base64WorkerScript = 'LyohIEBzZW50cnkvbm9kZSA4LjAuMC1iZXRhLjIgKGYyMTViYWIpIHwgaHR0cHM6Ly9naXRodWIuY29tL2dldHNlbnRyeS9zZW50cnktamF2YXNjcmlwdCAqLwppbXBvcnR7U2Vzc2lvbiBhcyB0fWZyb20iaW5zcGVjdG9yIjtpbXBvcnR7cGFyZW50UG9ydCBhcyBuLHdvcmtlckRhdGEgYXMgZX1mcm9tIndvcmtlcl90aHJlYWRzIjtpbXBvcnR7cG9zaXggYXMgcixzZXAgYXMgb31mcm9tInBhdGgiO2ltcG9ydCphcyBzIGZyb20ibm9kZTpodHRwIjtpbXBvcnQqYXMgaSBmcm9tIm5vZGU6aHR0cHMiO2ltcG9ydHtSZWFkYWJsZSBhcyBjfWZyb20ic3RyZWFtIjtpbXBvcnR7Y3JlYXRlR3ppcCBhcyB1fWZyb20iemxpYiI7aW1wb3J0KmFzIGEgZnJvbSJuZXQiO2ltcG9ydCphcyBmIGZyb20idGxzIjtpbXBvcnQqYXMgaCBmcm9tImh0dHAiO2NvbnN0IHA9T2JqZWN0LnByb3RvdHlwZS50b1N0cmluZztmdW5jdGlvbiBsKHQsbil7cmV0dXJuIHAuY2FsbCh0KT09PWBbb2JqZWN0ICR7bn1dYH1mdW5jdGlvbiBkKHQpe3JldHVybiBsKHQsIk9iamVjdCIpfWZ1bmN0aW9uIG0odCl7cmV0dXJuIEJvb2xlYW4odCYmdC50aGVuJiYiZnVuY3Rpb24iPT10eXBlb2YgdC50aGVuKX1mdW5jdGlvbiBnKHQsbil7dHJ5e3JldHVybiB0IGluc3RhbmNlb2Ygbn1jYXRjaCh0KXtyZXR1cm4hMX19Y29uc3QgeT1nbG9iYWxUaGlzO2Z1bmN0aW9uIGIodCxuLGUpe2NvbnN0IHI9ZXx8eSxvPXIuX19TRU5UUllfXz1yLl9fU0VOVFJZX198fHt9O3JldHVybiBvW3RdfHwob1t0XT1uKCkpfWNvbnN0IHY9eSxfPTgwO2Z1bmN0aW9uIHcodCxuKXtjb25zdCBlPXQscj1bXTtsZXQgbyxzLGksYyx1O2lmKCFlfHwhZS50YWdOYW1lKXJldHVybiIiO2lmKHYuSFRNTEVsZW1lbnQmJmUgaW5zdGFuY2VvZiBIVE1MRWxlbWVudCYmZS5kYXRhc2V0KXtpZihlLmRhdGFzZXQuc2VudHJ5Q29tcG9uZW50KXJldHVybiBlLmRhdGFzZXQuc2VudHJ5Q29tcG9uZW50O2lmKGUuZGF0YXNldC5zZW50cnlFbGVtZW50KXJldHVybiBlLmRhdGFzZXQuc2VudHJ5RWxlbWVudH1yLnB1c2goZS50YWdOYW1lLnRvTG93ZXJDYXNlKCkpO2NvbnN0IGE9biYmbi5sZW5ndGg/bi5maWx0ZXIoKHQ9PmUuZ2V0QXR0cmlidXRlKHQpKSkubWFwKCh0PT5bdCxlLmdldEF0dHJpYnV0ZSh0KV0pKTpudWxsO2lmKGEmJmEubGVuZ3RoKWEuZm9yRWFjaCgodD0+e3IucHVzaChgWyR7dFswXX09IiR7dFsxXX0iXWApfSkpO2Vsc2UgaWYoZS5pZCYmci5wdXNoKGAjJHtlLmlkfWApLG89ZS5jbGFzc05hbWUsbyYmbChvLCJTdHJpbmciKSlmb3Iocz1vLnNwbGl0KC9ccysvKSx1PTA7dTxzLmxlbmd0aDt1Kyspci5wdXNoKGAuJHtzW3VdfWApO2NvbnN0IGY9WyJhcmlhLWxhYmVsIiwidHlwZSIsIm5hbWUiLCJ0aXRsZSIsImFsdCJdO2Zvcih1PTA7dTxmLmxlbmd0aDt1KyspaT1mW3VdLGM9ZS5nZXRBdHRyaWJ1dGUoaSksYyYmci5wdXNoKGBbJHtpfT0iJHtjfSJdYCk7cmV0dXJuIHIuam9pbigiIil9Y29uc3QgUz0idW5kZWZpbmVkIj09dHlwZW9mIF9fU0VOVFJZX0RFQlVHX198fF9fU0VOVFJZX0RFQlVHX18sJD1bImRlYnVnIiwiaW5mbyIsIndhcm4iLCJlcnJvciIsImxvZyIsImFzc2VydCIsInRyYWNlIl0sRT17fTtmdW5jdGlvbiB4KHQpe2lmKCEoImNvbnNvbGUiaW4geSkpcmV0dXJuIHQoKTtjb25zdCBuPXkuY29uc29sZSxlPXt9LHI9T2JqZWN0LmtleXMoRSk7ci5mb3JFYWNoKCh0PT57Y29uc3Qgcj1FW3RdO2VbdF09blt0XSxuW3RdPXJ9KSk7dHJ5e3JldHVybiB0KCl9ZmluYWxseXtyLmZvckVhY2goKHQ9PntuW3RdPWVbdF19KSl9fWNvbnN0IE49ZnVuY3Rpb24oKXtsZXQgdD0hMTtjb25zdCBuPXtlbmFibGU6KCk9Pnt0PSEwfSxkaXNhYmxlOigpPT57dD0hMX0saXNFbmFibGVkOigpPT50fTtyZXR1cm4gUz8kLmZvckVhY2goKGU9PntuW2VdPSguLi5uKT0+e3QmJngoKCgpPT57eS5jb25zb2xlW2VdKGBTZW50cnkgTG9nZ2VyIFske2V9XTpgLC4uLm4pfSkpfX0pKTokLmZvckVhY2goKHQ9PntuW3RdPSgpPT57fX0pKSxufSgpO2Z1bmN0aW9uIGsodCxuPSExKXtjb25zdHtob3N0OmUscGF0aDpyLHBhc3M6byxwb3J0OnMscHJvamVjdElkOmkscHJvdG9jb2w6YyxwdWJsaWNLZXk6dX09dDtyZXR1cm5gJHtjfTovLyR7dX0ke24mJm8/YDoke299YDoiIn1AJHtlfSR7cz9gOiR7c31gOiIifS8ke3I/YCR7cn0vYDpyfSR7aX1gfWNsYXNzIEMgZXh0ZW5kcyBFcnJvcntjb25zdHJ1Y3Rvcih0LG49Indhcm4iKXtzdXBlcih0KSx0aGlzLm1lc3NhZ2U9dCx0aGlzLm5hbWU9bmV3LnRhcmdldC5wcm90b3R5cGUuY29uc3RydWN0b3IubmFtZSxPYmplY3Quc2V0UHJvdG90eXBlT2YodGhpcyxuZXcudGFyZ2V0LnByb3RvdHlwZSksdGhpcy5sb2dMZXZlbD1ufX1mdW5jdGlvbiBEKHQpe2lmKGZ1bmN0aW9uKHQpe3N3aXRjaChwLmNhbGwodCkpe2Nhc2UiW29iamVjdCBFcnJvcl0iOmNhc2UiW29iamVjdCBFeGNlcHRpb25dIjpjYXNlIltvYmplY3QgRE9NRXhjZXB0aW9uXSI6cmV0dXJuITA7ZGVmYXVsdDpyZXR1cm4gZyh0LEVycm9yKX19KHQpKXJldHVybnttZXNzYWdlOnQubWVzc2FnZSxuYW1lOnQubmFtZSxzdGFjazp0LnN0YWNrLC4uLk8odCl9O2lmKG49dCwidW5kZWZpbmVkIiE9dHlwZW9mIEV2ZW50JiZnKG4sRXZlbnQpKXtjb25zdCBuPXt0eXBlOnQudHlwZSx0YXJnZXQ6VCh0LnRhcmdldCksY3VycmVudFRhcmdldDpUKHQuY3VycmVudFRhcmdldCksLi4uTyh0KX07cmV0dXJuInVuZGVmaW5lZCIhPXR5cGVvZiBDdXN0b21FdmVudCYmZyh0LEN1c3RvbUV2ZW50KSYmKG4uZGV0YWlsPXQuZGV0YWlsKSxufXJldHVybiB0O3ZhciBufWZ1bmN0aW9uIFQodCl7dHJ5e3JldHVybiBuPXQsInVuZGVmaW5lZCIhPXR5cGVvZiBFbGVtZW50JiZnKG4sRWxlbWVudCk/ZnVuY3Rpb24odCxuPXt9KXtpZighdClyZXR1cm4iPHVua25vd24+Ijt0cnl7bGV0IGU9dDtjb25zdCByPTUsbz1bXTtsZXQgcz0wLGk9MDtjb25zdCBjPSIgPiAiLHU9Yy5sZW5ndGg7bGV0IGE7Y29uc3QgZj1BcnJheS5pc0FycmF5KG4pP246bi5rZXlBdHRycyxoPSFBcnJheS5pc0FycmF5KG4pJiZuLm1heFN0cmluZ0xlbmd0aHx8Xztmb3IoO2UmJnMrKzxyJiYoYT13KGUsZiksISgiaHRtbCI9PT1hfHxzPjEmJmkrby5sZW5ndGgqdSthLmxlbmd0aD49aCkpOylvLnB1c2goYSksaSs9YS5sZW5ndGgsZT1lLnBhcmVudE5vZGU7cmV0dXJuIG8ucmV2ZXJzZSgpLmpvaW4oYyl9Y2F0Y2godCl7cmV0dXJuIjx1bmtub3duPiJ9fSh0KTpPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwodCl9Y2F0Y2godCl7cmV0dXJuIjx1bmtub3duPiJ9dmFyIG59ZnVuY3Rpb24gTyh0KXtpZigib2JqZWN0Ij09dHlwZW9mIHQmJm51bGwhPT10KXtjb25zdCBuPXt9O2Zvcihjb25zdCBlIGluIHQpT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHQsZSkmJihuW2VdPXRbZV0pO3JldHVybiBufXJldHVybnt9fWZ1bmN0aW9uIGoodCl7cmV0dXJuIFIodCxuZXcgTWFwKX1mdW5jdGlvbiBSKHQsbil7aWYoZnVuY3Rpb24odCl7aWYoIWQodCkpcmV0dXJuITE7dHJ5e2NvbnN0IG49T2JqZWN0LmdldFByb3RvdHlwZU9mKHQpLmNvbnN0cnVjdG9yLm5hbWU7cmV0dXJuIW58fCJPYmplY3QiPT09bn1jYXRjaCh0KXtyZXR1cm4hMH19KHQpKXtjb25zdCBlPW4uZ2V0KHQpO2lmKHZvaWQgMCE9PWUpcmV0dXJuIGU7Y29uc3Qgcj17fTtuLnNldCh0LHIpO2Zvcihjb25zdCBlIG9mIE9iamVjdC5rZXlzKHQpKXZvaWQgMCE9PXRbZV0mJihyW2VdPVIodFtlXSxuKSk7cmV0dXJuIHJ9aWYoQXJyYXkuaXNBcnJheSh0KSl7Y29uc3QgZT1uLmdldCh0KTtpZih2b2lkIDAhPT1lKXJldHVybiBlO2NvbnN0IHI9W107cmV0dXJuIG4uc2V0KHQsciksdC5mb3JFYWNoKCh0PT57ci5wdXNoKFIodCxuKSl9KSkscn1yZXR1cm4gdH1jb25zdCBBPTUwLEk9Ij8iLFA9L2NhcHR1cmVNZXNzYWdlfGNhcHR1cmVFeGNlcHRpb24vO2NvbnN0IFU9Ijxhbm9ueW1vdXM+IjtmdW5jdGlvbiBNKCl7Y29uc3QgdD15LG49dC5jcnlwdG98fHQubXNDcnlwdG87bGV0IGU9KCk9PjE2Kk1hdGgucmFuZG9tKCk7dHJ5e2lmKG4mJm4ucmFuZG9tVVVJRClyZXR1cm4gbi5yYW5kb21VVUlEKCkucmVwbGFjZSgvLS9nLCIiKTtuJiZuLmdldFJhbmRvbVZhbHVlcyYmKGU9KCk9Pntjb25zdCB0PW5ldyBVaW50OEFycmF5KDEpO3JldHVybiBuLmdldFJhbmRvbVZhbHVlcyh0KSx0WzBdfSl9Y2F0Y2godCl7fXJldHVybihbMWU3XSsxZTMrNGUzKzhlMysxZTExKS5yZXBsYWNlKC9bMDE4XS9nLCh0PT4odF4oMTUmZSgpKT4+dC80KS50b1N0cmluZygxNikpKX1mdW5jdGlvbiBMKHQsbj0xMDAsZT0xLzApe3RyeXtyZXR1cm4gQigiIix0LG4sZSl9Y2F0Y2godCl7cmV0dXJue0VSUk9SOmAqKm5vbi1zZXJpYWxpemFibGUqKiAoJHt0fSlgfX19ZnVuY3Rpb24gQih0LG4sZT0xLzAscj0xLzAsbz1mdW5jdGlvbigpe2NvbnN0IHQ9ImZ1bmN0aW9uIj09dHlwZW9mIFdlYWtTZXQsbj10P25ldyBXZWFrU2V0OltdO3JldHVybltmdW5jdGlvbihlKXtpZih0KXJldHVybiEhbi5oYXMoZSl8fChuLmFkZChlKSwhMSk7Zm9yKGxldCB0PTA7dDxuLmxlbmd0aDt0KyspaWYoblt0XT09PWUpcmV0dXJuITA7cmV0dXJuIG4ucHVzaChlKSwhMX0sZnVuY3Rpb24oZSl7aWYodCluLmRlbGV0ZShlKTtlbHNlIGZvcihsZXQgdD0wO3Q8bi5sZW5ndGg7dCsrKWlmKG5bdF09PT1lKXtuLnNwbGljZSh0LDEpO2JyZWFrfX1dfSgpKXtjb25zdFtzLGldPW87aWYobnVsbD09bnx8WyJudW1iZXIiLCJib29sZWFuIiwic3RyaW5nIl0uaW5jbHVkZXModHlwZW9mIG4pJiYhTnVtYmVyLmlzTmFOKG4pKXJldHVybiBuO2NvbnN0IGM9ZnVuY3Rpb24odCxuKXt0cnl7aWYoImRvbWFpbiI9PT10JiZuJiYib2JqZWN0Ij09dHlwZW9mIG4mJm4udClyZXR1cm4iW0RvbWFpbl0iO2lmKCJkb21haW5FbWl0dGVyIj09PXQpcmV0dXJuIltEb21haW5FbWl0dGVyXSI7aWYoInVuZGVmaW5lZCIhPXR5cGVvZiBnbG9iYWwmJm49PT1nbG9iYWwpcmV0dXJuIltHbG9iYWxdIjtpZigidW5kZWZpbmVkIiE9dHlwZW9mIHdpbmRvdyYmbj09PXdpbmRvdylyZXR1cm4iW1dpbmRvd10iO2lmKCJ1bmRlZmluZWQiIT10eXBlb2YgZG9jdW1lbnQmJm49PT1kb2N1bWVudClyZXR1cm4iW0RvY3VtZW50XSI7aWYoIm9iamVjdCI9PXR5cGVvZihlPW4pJiZudWxsIT09ZSYmKGUuX19pc1Z1ZXx8ZS5vKSlyZXR1cm4iW1Z1ZVZpZXdNb2RlbF0iO2lmKGZ1bmN0aW9uKHQpe3JldHVybiBkKHQpJiYibmF0aXZlRXZlbnQiaW4gdCYmInByZXZlbnREZWZhdWx0ImluIHQmJiJzdG9wUHJvcGFnYXRpb24iaW4gdH0obikpcmV0dXJuIltTeW50aGV0aWNFdmVudF0iO2lmKCJudW1iZXIiPT10eXBlb2YgbiYmbiE9bilyZXR1cm4iW05hTl0iO2lmKCJmdW5jdGlvbiI9PXR5cGVvZiBuKXJldHVybmBbRnVuY3Rpb246ICR7ZnVuY3Rpb24odCl7dHJ5e3JldHVybiB0JiYiZnVuY3Rpb24iPT10eXBlb2YgdCYmdC5uYW1lfHxVfWNhdGNoKHQpe3JldHVybiBVfX0obil9XWA7aWYoInN5bWJvbCI9PXR5cGVvZiBuKXJldHVybmBbJHtTdHJpbmcobil9XWA7aWYoImJpZ2ludCI9PXR5cGVvZiBuKXJldHVybmBbQmlnSW50OiAke1N0cmluZyhuKX1dYDtjb25zdCByPWZ1bmN0aW9uKHQpe2NvbnN0IG49T2JqZWN0LmdldFByb3RvdHlwZU9mKHQpO3JldHVybiBuP24uY29uc3RydWN0b3IubmFtZToibnVsbCBwcm90b3R5cGUifShuKTtyZXR1cm4vXkhUTUwoXHcqKUVsZW1lbnQkLy50ZXN0KHIpP2BbSFRNTEVsZW1lbnQ6ICR7cn1dYDpgW29iamVjdCAke3J9XWB9Y2F0Y2godCl7cmV0dXJuYCoqbm9uLXNlcmlhbGl6YWJsZSoqICgke3R9KWB9dmFyIGV9KHQsbik7aWYoIWMuc3RhcnRzV2l0aCgiW29iamVjdCAiKSlyZXR1cm4gYztpZihuLl9fc2VudHJ5X3NraXBfbm9ybWFsaXphdGlvbl9fKXJldHVybiBuO2NvbnN0IHU9Im51bWJlciI9PXR5cGVvZiBuLl9fc2VudHJ5X292ZXJyaWRlX25vcm1hbGl6YXRpb25fZGVwdGhfXz9uLl9fc2VudHJ5X292ZXJyaWRlX25vcm1hbGl6YXRpb25fZGVwdGhfXzplO2lmKDA9PT11KXJldHVybiBjLnJlcGxhY2UoIm9iamVjdCAiLCIiKTtpZihzKG4pKXJldHVybiJbQ2lyY3VsYXIgfl0iO2NvbnN0IGE9bjtpZihhJiYiZnVuY3Rpb24iPT10eXBlb2YgYS50b0pTT04pdHJ5e3JldHVybiBCKCIiLGEudG9KU09OKCksdS0xLHIsbyl9Y2F0Y2godCl7fWNvbnN0IGY9QXJyYXkuaXNBcnJheShuKT9bXTp7fTtsZXQgaD0wO2NvbnN0IHA9RChuKTtmb3IoY29uc3QgdCBpbiBwKXtpZighT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHAsdCkpY29udGludWU7aWYoaD49cil7Zlt0XT0iW01heFByb3BlcnRpZXMgfl0iO2JyZWFrfWNvbnN0IG49cFt0XTtmW3RdPUIodCxuLHUtMSxyLG8pLGgrK31yZXR1cm4gaShuKSxmfWZ1bmN0aW9uIEcodCxuKXtjb25zdCBlPW4ucmVwbGFjZSgvXFwvZywiLyIpLnJlcGxhY2UoL1t8XFx7fSgpW1xdXiQrKj8uXS9nLCJcXCQmIik7bGV0IHI9dDt0cnl7cj1kZWNvZGVVUkkodCl9Y2F0Y2godCl7fXJldHVybiByLnJlcGxhY2UoL1xcL2csIi8iKS5yZXBsYWNlKC93ZWJwYWNrOlwvPy9nLCIiKS5yZXBsYWNlKG5ldyBSZWdFeHAoYChmaWxlOi8vKT8vKiR7ZX0vKmAsImlnIiksImFwcDovLy8iKX1jb25zdCBKPS9eKFxTKzpcXHxcLz8pKFtcc1xTXSo/KSgoPzpcLnsxLDJ9fFteL1xcXSs/fCkoXC5bXi4vXFxdKnwpKSg/OlsvXFxdKikkLztmdW5jdGlvbiB6KHQpe2NvbnN0IG49ZnVuY3Rpb24odCl7Y29uc3Qgbj10Lmxlbmd0aD4xMDI0P2A8dHJ1bmNhdGVkPiR7dC5zbGljZSgtMTAyNCl9YDp0LGU9Si5leGVjKG4pO3JldHVybiBlP2Uuc2xpY2UoMSk6W119KHQpLGU9blswXTtsZXQgcj1uWzFdO3JldHVybiBlfHxyPyhyJiYocj1yLnNsaWNlKDAsci5sZW5ndGgtMSkpLGUrcik6Ii4ifXZhciBIO2Z1bmN0aW9uIFcodCl7cmV0dXJuIG5ldyBZKChuPT57bih0KX0pKX0hZnVuY3Rpb24odCl7dFt0LlBFTkRJTkc9MF09IlBFTkRJTkciO3RbdC5SRVNPTFZFRD0xXT0iUkVTT0xWRUQiO3RbdC5SRUpFQ1RFRD0yXT0iUkVKRUNURUQifShIfHwoSD17fSkpO2NsYXNzIFl7Y29uc3RydWN0b3IodCl7WS5wcm90b3R5cGUuX19pbml0LmNhbGwodGhpcyksWS5wcm90b3R5cGUuX19pbml0Mi5jYWxsKHRoaXMpLFkucHJvdG90eXBlLl9faW5pdDMuY2FsbCh0aGlzKSxZLnByb3RvdHlwZS5fX2luaXQ0LmNhbGwodGhpcyksdGhpcy5pPUguUEVORElORyx0aGlzLnU9W107dHJ5e3QodGhpcy5oLHRoaXMucCl9Y2F0Y2godCl7dGhpcy5wKHQpfX10aGVuKHQsbil7cmV0dXJuIG5ldyBZKCgoZSxyKT0+e3RoaXMudS5wdXNoKFshMSxuPT57aWYodCl0cnl7ZSh0KG4pKX1jYXRjaCh0KXtyKHQpfWVsc2UgZShuKX0sdD0+e2lmKG4pdHJ5e2Uobih0KSl9Y2F0Y2godCl7cih0KX1lbHNlIHIodCl9XSksdGhpcy5sKCl9KSl9Y2F0Y2godCl7cmV0dXJuIHRoaXMudGhlbigodD0+dCksdCl9ZmluYWxseSh0KXtyZXR1cm4gbmV3IFkoKChuLGUpPT57bGV0IHIsbztyZXR1cm4gdGhpcy50aGVuKChuPT57bz0hMSxyPW4sdCYmdCgpfSksKG49PntvPSEwLHI9bix0JiZ0KCl9KSkudGhlbigoKCk9PntvP2Uocik6bihyKX0pKX0pKX1fX2luaXQoKXt0aGlzLmg9dD0+e3RoaXMubShILlJFU09MVkVELHQpfX1fX2luaXQyKCl7dGhpcy5wPXQ9Pnt0aGlzLm0oSC5SRUpFQ1RFRCx0KX19X19pbml0Mygpe3RoaXMubT0odCxuKT0+e3RoaXMuaT09PUguUEVORElORyYmKG0obik/bi50aGVuKHRoaXMuaCx0aGlzLnApOih0aGlzLmk9dCx0aGlzLnY9bix0aGlzLmwoKSkpfX1fX2luaXQ0KCl7dGhpcy5sPSgpPT57aWYodGhpcy5pPT09SC5QRU5ESU5HKXJldHVybjtjb25zdCB0PXRoaXMudS5zbGljZSgpO3RoaXMudT1bXSx0LmZvckVhY2goKHQ9Pnt0WzBdfHwodGhpcy5pPT09SC5SRVNPTFZFRCYmdFsxXSh0aGlzLnYpLHRoaXMuaT09PUguUkVKRUNURUQmJnRbMl0odGhpcy52KSx0WzBdPSEwKX0pKX19fWZ1bmN0aW9uIHEodCl7Y29uc3Qgbj1bXTtmdW5jdGlvbiBlKHQpe3JldHVybiBuLnNwbGljZShuLmluZGV4T2YodCksMSlbMF19cmV0dXJueyQ6bixhZGQ6ZnVuY3Rpb24ocil7aWYoISh2b2lkIDA9PT10fHxuLmxlbmd0aDx0KSlyZXR1cm4gbz1uZXcgQygiTm90IGFkZGluZyBQcm9taXNlIGJlY2F1c2UgYnVmZmVyIGxpbWl0IHdhcyByZWFjaGVkLiIpLG5ldyBZKCgodCxuKT0+e24obyl9KSk7dmFyIG87Y29uc3Qgcz1yKCk7cmV0dXJuLTE9PT1uLmluZGV4T2YocykmJm4ucHVzaChzKSxzLnRoZW4oKCgpPT5lKHMpKSkudGhlbihudWxsLCgoKT0+ZShzKS50aGVuKG51bGwsKCgpPT57fSkpKSksc30sZHJhaW46ZnVuY3Rpb24odCl7cmV0dXJuIG5ldyBZKCgoZSxyKT0+e2xldCBvPW4ubGVuZ3RoO2lmKCFvKXJldHVybiBlKCEwKTtjb25zdCBzPXNldFRpbWVvdXQoKCgpPT57dCYmdD4wJiZlKCExKX0pLHQpO24uZm9yRWFjaCgodD0+e1codCkudGhlbigoKCk9PnstLW98fChjbGVhclRpbWVvdXQocyksZSghMCkpfSkscil9KSl9KSl9fX1mdW5jdGlvbiBGKHQsbj0hMSl7cmV0dXJuIShufHx0JiYhdC5zdGFydHNXaXRoKCIvIikmJiF0Lm1hdGNoKC9eW0EtWl06LykmJiF0LnN0YXJ0c1dpdGgoIi4iKSYmIXQubWF0Y2goL15bYS16QS1aXShbYS16QS1aMC05LlwtK10pKjpcL1wvLykpJiZ2b2lkIDAhPT10JiYhdC5pbmNsdWRlcygibm9kZV9tb2R1bGVzLyIpfWNvbnN0IEs9MWUzO2Z1bmN0aW9uIFYoKXtyZXR1cm4gRGF0ZS5ub3coKS9LfWNvbnN0IFo9ZnVuY3Rpb24oKXtjb25zdHtwZXJmb3JtYW5jZTp0fT15O2lmKCF0fHwhdC5ub3cpcmV0dXJuIFY7Y29uc3Qgbj1EYXRlLm5vdygpLXQubm93KCksZT1udWxsPT10LnRpbWVPcmlnaW4/bjp0LnRpbWVPcmlnaW47cmV0dXJuKCk9PihlK3Qubm93KCkpL0t9KCk7ZnVuY3Rpb24gUSh0LG49W10pe3JldHVyblt0LG5dfWZ1bmN0aW9uIFgodCxuKXtjb25zdCBlPXRbMV07Zm9yKGNvbnN0IHQgb2YgZSl7aWYobih0LHRbMF0udHlwZSkpcmV0dXJuITB9cmV0dXJuITF9ZnVuY3Rpb24gdHQodCl7cmV0dXJuIHkuX19TRU5UUllfXyYmeS5fX1NFTlRSWV9fLmVuY29kZVBvbHlmaWxsP3kuX19TRU5UUllfXy5lbmNvZGVQb2x5ZmlsbCh0KToobmV3IFRleHRFbmNvZGVyKS5lbmNvZGUodCl9ZnVuY3Rpb24gbnQodCl7Y29uc3RbbixlXT10O2xldCByPUpTT04uc3RyaW5naWZ5KG4pO2Z1bmN0aW9uIG8odCl7InN0cmluZyI9PXR5cGVvZiByP3I9InN0cmluZyI9PXR5cGVvZiB0P3IrdDpbdHQociksdF06ci5wdXNoKCJzdHJpbmciPT10eXBlb2YgdD90dCh0KTp0KX1mb3IoY29uc3QgdCBvZiBlKXtjb25zdFtuLGVdPXQ7aWYobyhgXG4ke0pTT04uc3RyaW5naWZ5KG4pfVxuYCksInN0cmluZyI9PXR5cGVvZiBlfHxlIGluc3RhbmNlb2YgVWludDhBcnJheSlvKGUpO2Vsc2V7bGV0IHQ7dHJ5e3Q9SlNPTi5zdHJpbmdpZnkoZSl9Y2F0Y2gobil7dD1KU09OLnN0cmluZ2lmeShMKGUpKX1vKHQpfX1yZXR1cm4ic3RyaW5nIj09dHlwZW9mIHI/cjpmdW5jdGlvbih0KXtjb25zdCBuPXQucmVkdWNlKCgodCxuKT0+dCtuLmxlbmd0aCksMCksZT1uZXcgVWludDhBcnJheShuKTtsZXQgcj0wO2Zvcihjb25zdCBuIG9mIHQpZS5zZXQobixyKSxyKz1uLmxlbmd0aDtyZXR1cm4gZX0ocil9KCgpPT57Y29uc3R7cGVyZm9ybWFuY2U6dH09eTtpZighdHx8IXQubm93KXJldHVybjtjb25zdCBuPTM2ZTUsZT10Lm5vdygpLHI9RGF0ZS5ub3coKSxvPXQudGltZU9yaWdpbj9NYXRoLmFicyh0LnRpbWVPcmlnaW4rZS1yKTpuLHM9bzxuLGk9dC50aW1pbmcmJnQudGltaW5nLm5hdmlnYXRpb25TdGFydCxjPSJudW1iZXIiPT10eXBlb2YgaT9NYXRoLmFicyhpK2Utcik6bjsoc3x8YzxuKSYmKG88PWMmJnQudGltZU9yaWdpbil9KSgpO2NvbnN0IGV0PXtzZXNzaW9uOiJzZXNzaW9uIixzZXNzaW9uczoic2Vzc2lvbiIsYXR0YWNobWVudDoiYXR0YWNobWVudCIsdHJhbnNhY3Rpb246InRyYW5zYWN0aW9uIixldmVudDoiZXJyb3IiLGNsaWVudF9yZXBvcnQ6ImludGVybmFsIix1c2VyX3JlcG9ydDoiZGVmYXVsdCIscHJvZmlsZToicHJvZmlsZSIscmVwbGF5X2V2ZW50OiJyZXBsYXkiLHJlcGxheV9yZWNvcmRpbmc6InJlcGxheSIsY2hlY2tfaW46Im1vbml0b3IiLGZlZWRiYWNrOiJmZWVkYmFjayIsc3Bhbjoic3BhbiIsc3RhdHNkOiJtZXRyaWNfYnVja2V0In07ZnVuY3Rpb24gcnQodCl7cmV0dXJuIGV0W3RdfWZ1bmN0aW9uIG90KHQpe2lmKCF0fHwhdC5zZGspcmV0dXJuO2NvbnN0e25hbWU6bix2ZXJzaW9uOmV9PXQuc2RrO3JldHVybntuYW1lOm4sdmVyc2lvbjplfX1jb25zdCBzdD02ZTQ7ZnVuY3Rpb24gaXQodCx7c3RhdHVzQ29kZTpuLGhlYWRlcnM6ZX0scj1EYXRlLm5vdygpKXtjb25zdCBvPXsuLi50fSxzPWUmJmVbIngtc2VudHJ5LXJhdGUtbGltaXRzIl0saT1lJiZlWyJyZXRyeS1hZnRlciJdO2lmKHMpZm9yKGNvbnN0IHQgb2Ygcy50cmltKCkuc3BsaXQoIiwiKSl7Y29uc3RbbixlLCwsc109dC5zcGxpdCgiOiIsNSksaT1wYXJzZUludChuLDEwKSxjPTFlMyooaXNOYU4oaSk/NjA6aSk7aWYoZSlmb3IoY29uc3QgdCBvZiBlLnNwbGl0KCI7IikpIm1ldHJpY19idWNrZXQiPT09dCYmcyYmIXMuc3BsaXQoIjsiKS5pbmNsdWRlcygiY3VzdG9tIil8fChvW3RdPXIrYyk7ZWxzZSBvLmFsbD1yK2N9ZWxzZSBpP28uYWxsPXIrZnVuY3Rpb24odCxuPURhdGUubm93KCkpe2NvbnN0IGU9cGFyc2VJbnQoYCR7dH1gLDEwKTtpZighaXNOYU4oZSkpcmV0dXJuIDFlMyplO2NvbnN0IHI9RGF0ZS5wYXJzZShgJHt0fWApO3JldHVybiBpc05hTihyKT9zdDpyLW59KGkscik6NDI5PT09biYmKG8uYWxsPXIrNmU0KTtyZXR1cm4gb31jb25zdCBjdD0idW5kZWZpbmVkIj09dHlwZW9mIF9fU0VOVFJZX0RFQlVHX198fF9fU0VOVFJZX0RFQlVHX187ZnVuY3Rpb24gdXQoKXtyZXR1cm4gYXQoeSkseX1mdW5jdGlvbiBhdCh0KXtyZXR1cm4gdC5fX1NFTlRSWV9ffHwodC5fX1NFTlRSWV9fPXtleHRlbnNpb25zOnt9fSksdC5fX1NFTlRSWV9ffWZ1bmN0aW9uIGZ0KHQpe2NvbnN0IG49WigpLGU9e3NpZDpNKCksaW5pdDohMCx0aW1lc3RhbXA6bixzdGFydGVkOm4sZHVyYXRpb246MCxzdGF0dXM6Im9rIixlcnJvcnM6MCxpZ25vcmVEdXJhdGlvbjohMSx0b0pTT046KCk9PmZ1bmN0aW9uKHQpe3JldHVybiBqKHtzaWQ6YCR7dC5zaWR9YCxpbml0OnQuaW5pdCxzdGFydGVkOm5ldyBEYXRlKDFlMyp0LnN0YXJ0ZWQpLnRvSVNPU3RyaW5nKCksdGltZXN0YW1wOm5ldyBEYXRlKDFlMyp0LnRpbWVzdGFtcCkudG9JU09TdHJpbmcoKSxzdGF0dXM6dC5zdGF0dXMsZXJyb3JzOnQuZXJyb3JzLGRpZDoibnVtYmVyIj09dHlwZW9mIHQuZGlkfHwic3RyaW5nIj09dHlwZW9mIHQuZGlkP2Ake3QuZGlkfWA6dm9pZCAwLGR1cmF0aW9uOnQuZHVyYXRpb24sYWJub3JtYWxfbWVjaGFuaXNtOnQuYWJub3JtYWxfbWVjaGFuaXNtLGF0dHJzOntyZWxlYXNlOnQucmVsZWFzZSxlbnZpcm9ubWVudDp0LmVudmlyb25tZW50LGlwX2FkZHJlc3M6dC5pcEFkZHJlc3MsdXNlcl9hZ2VudDp0LnVzZXJBZ2VudH19KX0oZSl9O3JldHVybiB0JiZodChlLHQpLGV9ZnVuY3Rpb24gaHQodCxuPXt9KXtpZihuLnVzZXImJighdC5pcEFkZHJlc3MmJm4udXNlci5pcF9hZGRyZXNzJiYodC5pcEFkZHJlc3M9bi51c2VyLmlwX2FkZHJlc3MpLHQuZGlkfHxuLmRpZHx8KHQuZGlkPW4udXNlci5pZHx8bi51c2VyLmVtYWlsfHxuLnVzZXIudXNlcm5hbWUpKSx0LnRpbWVzdGFtcD1uLnRpbWVzdGFtcHx8WigpLG4uYWJub3JtYWxfbWVjaGFuaXNtJiYodC5hYm5vcm1hbF9tZWNoYW5pc209bi5hYm5vcm1hbF9tZWNoYW5pc20pLG4uaWdub3JlRHVyYXRpb24mJih0Lmlnbm9yZUR1cmF0aW9uPW4uaWdub3JlRHVyYXRpb24pLG4uc2lkJiYodC5zaWQ9MzI9PT1uLnNpZC5sZW5ndGg/bi5zaWQ6TSgpKSx2b2lkIDAhPT1uLmluaXQmJih0LmluaXQ9bi5pbml0KSwhdC5kaWQmJm4uZGlkJiYodC5kaWQ9YCR7bi5kaWR9YCksIm51bWJlciI9PXR5cGVvZiBuLnN0YXJ0ZWQmJih0LnN0YXJ0ZWQ9bi5zdGFydGVkKSx0Lmlnbm9yZUR1cmF0aW9uKXQuZHVyYXRpb249dm9pZCAwO2Vsc2UgaWYoIm51bWJlciI9PXR5cGVvZiBuLmR1cmF0aW9uKXQuZHVyYXRpb249bi5kdXJhdGlvbjtlbHNle2NvbnN0IG49dC50aW1lc3RhbXAtdC5zdGFydGVkO3QuZHVyYXRpb249bj49MD9uOjB9bi5yZWxlYXNlJiYodC5yZWxlYXNlPW4ucmVsZWFzZSksbi5lbnZpcm9ubWVudCYmKHQuZW52aXJvbm1lbnQ9bi5lbnZpcm9ubWVudCksIXQuaXBBZGRyZXNzJiZuLmlwQWRkcmVzcyYmKHQuaXBBZGRyZXNzPW4uaXBBZGRyZXNzKSwhdC51c2VyQWdlbnQmJm4udXNlckFnZW50JiYodC51c2VyQWdlbnQ9bi51c2VyQWdlbnQpLCJudW1iZXIiPT10eXBlb2Ygbi5lcnJvcnMmJih0LmVycm9ycz1uLmVycm9ycyksbi5zdGF0dXMmJih0LnN0YXR1cz1uLnN0YXR1cyl9Y29uc3QgcHQ9Il9zZW50cnlTcGFuIjtmdW5jdGlvbiBsdCh0LG4pe24/ZnVuY3Rpb24odCxuLGUpe3RyeXtPYmplY3QuZGVmaW5lUHJvcGVydHkodCxuLHt2YWx1ZTplLHdyaXRhYmxlOiEwLGNvbmZpZ3VyYWJsZTohMH0pfWNhdGNoKGUpe1MmJk4ubG9nKGBGYWlsZWQgdG8gYWRkIG5vbi1lbnVtZXJhYmxlIHByb3BlcnR5ICIke259IiB0byBvYmplY3RgLHQpfX0odCxwdCxuKTpkZWxldGUgdFtwdF19ZnVuY3Rpb24gZHQodCl7cmV0dXJuIHRbcHRdfWNsYXNzIG10e2NvbnN0cnVjdG9yKCl7dGhpcy5fPSExLHRoaXMuUz1bXSx0aGlzLk49W10sdGhpcy5rPVtdLHRoaXMuQz1bXSx0aGlzLkQ9e30sdGhpcy5UPXt9LHRoaXMuTz17fSx0aGlzLmo9e30sdGhpcy5SPXt9LHRoaXMuQT1ndCgpfWNsb25lKCl7Y29uc3QgdD1uZXcgbXQ7cmV0dXJuIHQuaz1bLi4udGhpcy5rXSx0LlQ9ey4uLnRoaXMuVH0sdC5PPXsuLi50aGlzLk99LHQuaj17Li4udGhpcy5qfSx0LkQ9dGhpcy5ELHQuST10aGlzLkksdC5QPXRoaXMuUCx0LlU9dGhpcy5VLHQuTT10aGlzLk0sdC5OPVsuLi50aGlzLk5dLHQuTD10aGlzLkwsdC5DPVsuLi50aGlzLkNdLHQuUj17Li4udGhpcy5SfSx0LkE9ey4uLnRoaXMuQX0sdC5CPXRoaXMuQixsdCh0LGR0KHRoaXMpKSx0fXNldENsaWVudCh0KXt0aGlzLkI9dH1nZXRDbGllbnQoKXtyZXR1cm4gdGhpcy5CfWFkZFNjb3BlTGlzdGVuZXIodCl7dGhpcy5TLnB1c2godCl9YWRkRXZlbnRQcm9jZXNzb3IodCl7cmV0dXJuIHRoaXMuTi5wdXNoKHQpLHRoaXN9c2V0VXNlcih0KXtyZXR1cm4gdGhpcy5EPXR8fHtlbWFpbDp2b2lkIDAsaWQ6dm9pZCAwLGlwX2FkZHJlc3M6dm9pZCAwLHVzZXJuYW1lOnZvaWQgMH0sdGhpcy5QJiZodCh0aGlzLlAse3VzZXI6dH0pLHRoaXMuRygpLHRoaXN9Z2V0VXNlcigpe3JldHVybiB0aGlzLkR9Z2V0UmVxdWVzdFNlc3Npb24oKXtyZXR1cm4gdGhpcy5MfXNldFJlcXVlc3RTZXNzaW9uKHQpe3JldHVybiB0aGlzLkw9dCx0aGlzfXNldFRhZ3ModCl7cmV0dXJuIHRoaXMuVD17Li4udGhpcy5ULC4uLnR9LHRoaXMuRygpLHRoaXN9c2V0VGFnKHQsbil7cmV0dXJuIHRoaXMuVD17Li4udGhpcy5ULFt0XTpufSx0aGlzLkcoKSx0aGlzfXNldEV4dHJhcyh0KXtyZXR1cm4gdGhpcy5PPXsuLi50aGlzLk8sLi4udH0sdGhpcy5HKCksdGhpc31zZXRFeHRyYSh0LG4pe3JldHVybiB0aGlzLk89ey4uLnRoaXMuTyxbdF06bn0sdGhpcy5HKCksdGhpc31zZXRGaW5nZXJwcmludCh0KXtyZXR1cm4gdGhpcy5NPXQsdGhpcy5HKCksdGhpc31zZXRMZXZlbCh0KXtyZXR1cm4gdGhpcy5JPXQsdGhpcy5HKCksdGhpc31zZXRUcmFuc2FjdGlvbk5hbWUodCl7cmV0dXJuIHRoaXMuVT10LHRoaXMuRygpLHRoaXN9c2V0Q29udGV4dCh0LG4pe3JldHVybiBudWxsPT09bj9kZWxldGUgdGhpcy5qW3RdOnRoaXMualt0XT1uLHRoaXMuRygpLHRoaXN9c2V0U2Vzc2lvbih0KXtyZXR1cm4gdD90aGlzLlA9dDpkZWxldGUgdGhpcy5QLHRoaXMuRygpLHRoaXN9Z2V0U2Vzc2lvbigpe3JldHVybiB0aGlzLlB9dXBkYXRlKHQpe2lmKCF0KXJldHVybiB0aGlzO2NvbnN0IG49ImZ1bmN0aW9uIj09dHlwZW9mIHQ/dCh0aGlzKTp0LFtlLHJdPW4gaW5zdGFuY2VvZiBtdD9bbi5nZXRTY29wZURhdGEoKSxuLmdldFJlcXVlc3RTZXNzaW9uKCldOmQobik/W3QsdC5yZXF1ZXN0U2Vzc2lvbl06W10se3RhZ3M6byxleHRyYTpzLHVzZXI6aSxjb250ZXh0czpjLGxldmVsOnUsZmluZ2VycHJpbnQ6YT1bXSxwcm9wYWdhdGlvbkNvbnRleHQ6Zn09ZXx8e307cmV0dXJuIHRoaXMuVD17Li4udGhpcy5ULC4uLm99LHRoaXMuTz17Li4udGhpcy5PLC4uLnN9LHRoaXMuaj17Li4udGhpcy5qLC4uLmN9LGkmJk9iamVjdC5rZXlzKGkpLmxlbmd0aCYmKHRoaXMuRD1pKSx1JiYodGhpcy5JPXUpLGEubGVuZ3RoJiYodGhpcy5NPWEpLGYmJih0aGlzLkE9ZiksciYmKHRoaXMuTD1yKSx0aGlzfWNsZWFyKCl7cmV0dXJuIHRoaXMuaz1bXSx0aGlzLlQ9e30sdGhpcy5PPXt9LHRoaXMuRD17fSx0aGlzLmo9e30sdGhpcy5JPXZvaWQgMCx0aGlzLlU9dm9pZCAwLHRoaXMuTT12b2lkIDAsdGhpcy5MPXZvaWQgMCx0aGlzLlA9dm9pZCAwLGx0KHRoaXMsdm9pZCAwKSx0aGlzLkM9W10sdGhpcy5BPWd0KCksdGhpcy5HKCksdGhpc31hZGRCcmVhZGNydW1iKHQsbil7Y29uc3QgZT0ibnVtYmVyIj09dHlwZW9mIG4/bjoxMDA7aWYoZTw9MClyZXR1cm4gdGhpcztjb25zdCByPXt0aW1lc3RhbXA6VigpLC4uLnR9LG89dGhpcy5rO3JldHVybiBvLnB1c2gociksdGhpcy5rPW8ubGVuZ3RoPmU/by5zbGljZSgtZSk6byx0aGlzLkcoKSx0aGlzfWdldExhc3RCcmVhZGNydW1iKCl7cmV0dXJuIHRoaXMua1t0aGlzLmsubGVuZ3RoLTFdfWNsZWFyQnJlYWRjcnVtYnMoKXtyZXR1cm4gdGhpcy5rPVtdLHRoaXMuRygpLHRoaXN9YWRkQXR0YWNobWVudCh0KXtyZXR1cm4gdGhpcy5DLnB1c2godCksdGhpc31jbGVhckF0dGFjaG1lbnRzKCl7cmV0dXJuIHRoaXMuQz1bXSx0aGlzfWdldFNjb3BlRGF0YSgpe3JldHVybnticmVhZGNydW1iczp0aGlzLmssYXR0YWNobWVudHM6dGhpcy5DLGNvbnRleHRzOnRoaXMuaix0YWdzOnRoaXMuVCxleHRyYTp0aGlzLk8sdXNlcjp0aGlzLkQsbGV2ZWw6dGhpcy5JLGZpbmdlcnByaW50OnRoaXMuTXx8W10sZXZlbnRQcm9jZXNzb3JzOnRoaXMuTixwcm9wYWdhdGlvbkNvbnRleHQ6dGhpcy5BLHNka1Byb2Nlc3NpbmdNZXRhZGF0YTp0aGlzLlIsdHJhbnNhY3Rpb25OYW1lOnRoaXMuVSxzcGFuOmR0KHRoaXMpfX1zZXRTREtQcm9jZXNzaW5nTWV0YWRhdGEodCl7cmV0dXJuIHRoaXMuUj17Li4udGhpcy5SLC4uLnR9LHRoaXN9c2V0UHJvcGFnYXRpb25Db250ZXh0KHQpe3JldHVybiB0aGlzLkE9dCx0aGlzfWdldFByb3BhZ2F0aW9uQ29udGV4dCgpe3JldHVybiB0aGlzLkF9Y2FwdHVyZUV4Y2VwdGlvbih0LG4pe2NvbnN0IGU9biYmbi5ldmVudF9pZD9uLmV2ZW50X2lkOk0oKTtpZighdGhpcy5CKXJldHVybiBOLndhcm4oIk5vIGNsaWVudCBjb25maWd1cmVkIG9uIHNjb3BlIC0gd2lsbCBub3QgY2FwdHVyZSBleGNlcHRpb24hIiksZTtjb25zdCByPW5ldyBFcnJvcigiU2VudHJ5IHN5bnRoZXRpY0V4Y2VwdGlvbiIpO3JldHVybiB0aGlzLkIuY2FwdHVyZUV4Y2VwdGlvbih0LHtvcmlnaW5hbEV4Y2VwdGlvbjp0LHN5bnRoZXRpY0V4Y2VwdGlvbjpyLC4uLm4sZXZlbnRfaWQ6ZX0sdGhpcyksZX1jYXB0dXJlTWVzc2FnZSh0LG4sZSl7Y29uc3Qgcj1lJiZlLmV2ZW50X2lkP2UuZXZlbnRfaWQ6TSgpO2lmKCF0aGlzLkIpcmV0dXJuIE4ud2FybigiTm8gY2xpZW50IGNvbmZpZ3VyZWQgb24gc2NvcGUgLSB3aWxsIG5vdCBjYXB0dXJlIG1lc3NhZ2UhIikscjtjb25zdCBvPW5ldyBFcnJvcih0KTtyZXR1cm4gdGhpcy5CLmNhcHR1cmVNZXNzYWdlKHQsbix7b3JpZ2luYWxFeGNlcHRpb246dCxzeW50aGV0aWNFeGNlcHRpb246bywuLi5lLGV2ZW50X2lkOnJ9LHRoaXMpLHJ9Y2FwdHVyZUV2ZW50KHQsbil7Y29uc3QgZT1uJiZuLmV2ZW50X2lkP24uZXZlbnRfaWQ6TSgpO3JldHVybiB0aGlzLkI/KHRoaXMuQi5jYXB0dXJlRXZlbnQodCx7Li4ubixldmVudF9pZDplfSx0aGlzKSxlKTooTi53YXJuKCJObyBjbGllbnQgY29uZmlndXJlZCBvbiBzY29wZSAtIHdpbGwgbm90IGNhcHR1cmUgZXZlbnQhIiksZSl9Rygpe3RoaXMuX3x8KHRoaXMuXz0hMCx0aGlzLlMuZm9yRWFjaCgodD0+e3QodGhpcyl9KSksdGhpcy5fPSExKX19ZnVuY3Rpb24gZ3QoKXtyZXR1cm57dHJhY2VJZDpNKCksc3BhbklkOk0oKS5zdWJzdHJpbmcoMTYpfX1mdW5jdGlvbiB5dCgpe3JldHVybiAkdCh1dCgpKS5nZXRDdXJyZW50U2NvcGUoKS5nZXRDbGllbnQoKX1jbGFzcyBidHtjb25zdHJ1Y3Rvcih0LG4pe2xldCBlLHI7ZT10fHxuZXcgbXQscj1ufHxuZXcgbXQsdGhpcy5KPVt7c2NvcGU6ZX1dLHRoaXMuSD1yfXdpdGhTY29wZSh0KXtjb25zdCBuPXRoaXMuVygpO2xldCBlO3RyeXtlPXQobil9Y2F0Y2godCl7dGhyb3cgdGhpcy5ZKCksdH1yZXR1cm4gbShlKT9lLnRoZW4oKHQ9Pih0aGlzLlkoKSx0KSksKHQ9Pnt0aHJvdyB0aGlzLlkoKSx0fSkpOih0aGlzLlkoKSxlKX1nZXRDbGllbnQoKXtyZXR1cm4gdGhpcy5nZXRTdGFja1RvcCgpLmNsaWVudH1nZXRTY29wZSgpe3JldHVybiB0aGlzLmdldFN0YWNrVG9wKCkuc2NvcGV9Z2V0SXNvbGF0aW9uU2NvcGUoKXtyZXR1cm4gdGhpcy5IfWdldFN0YWNrKCl7cmV0dXJuIHRoaXMuSn1nZXRTdGFja1RvcCgpe3JldHVybiB0aGlzLkpbdGhpcy5KLmxlbmd0aC0xXX1XKCl7Y29uc3QgdD10aGlzLmdldFNjb3BlKCkuY2xvbmUoKTtyZXR1cm4gdGhpcy5nZXRTdGFjaygpLnB1c2goe2NsaWVudDp0aGlzLmdldENsaWVudCgpLHNjb3BlOnR9KSx0fVkoKXtyZXR1cm4hKHRoaXMuZ2V0U3RhY2soKS5sZW5ndGg8PTEpJiYhIXRoaXMuZ2V0U3RhY2soKS5wb3AoKX19ZnVuY3Rpb24gdnQoKXtjb25zdCB0PWF0KHV0KCkpO3JldHVybiB0Lmh1Ynx8KHQuaHViPW5ldyBidChiKCJkZWZhdWx0Q3VycmVudFNjb3BlIiwoKCk9Pm5ldyBtdCkpLGIoImRlZmF1bHRJc29sYXRpb25TY29wZSIsKCgpPT5uZXcgbXQpKSkpLHQuaHVifWZ1bmN0aW9uIF90KHQpe3JldHVybiB2dCgpLndpdGhTY29wZSh0KX1mdW5jdGlvbiB3dCh0LG4pe2NvbnN0IGU9dnQoKTtyZXR1cm4gZS53aXRoU2NvcGUoKCgpPT4oZS5nZXRTdGFja1RvcCgpLnNjb3BlPXQsbih0KSkpKX1mdW5jdGlvbiBTdCh0KXtyZXR1cm4gdnQoKS53aXRoU2NvcGUoKCgpPT50KHZ0KCkuZ2V0SXNvbGF0aW9uU2NvcGUoKSkpKX1mdW5jdGlvbiAkdCh0KXtjb25zdCBuPWF0KHQpO3JldHVybiBuLmFjcz9uLmFjczp7d2l0aElzb2xhdGlvblNjb3BlOlN0LHdpdGhTY29wZTpfdCx3aXRoU2V0U2NvcGU6d3Qsd2l0aFNldElzb2xhdGlvblNjb3BlOih0LG4pPT5TdChuKSxnZXRDdXJyZW50U2NvcGU6KCk9PnZ0KCkuZ2V0U2NvcGUoKSxnZXRJc29sYXRpb25TY29wZTooKT0+dnQoKS5nZXRJc29sYXRpb25TY29wZSgpfX1jb25zdCBFdD0ic2VudHJ5LnNvdXJjZSIseHQ9InNlbnRyeS5zYW1wbGVfcmF0ZSIsTnQ9InNlbnRyeS5vcCIsa3Q9InNlbnRyeS5vcmlnaW4iLEN0PTAsRHQ9MSxUdD0xO2Z1bmN0aW9uIE90KHQpe2NvbnN0e3NwYW5JZDpuLHRyYWNlSWQ6ZX09dC5zcGFuQ29udGV4dCgpLHtkYXRhOnIsb3A6byxwYXJlbnRfc3Bhbl9pZDpzLHN0YXR1czppLG9yaWdpbjpjfT1BdCh0KTtyZXR1cm4gaih7ZGF0YTpyLG9wOm8scGFyZW50X3NwYW5faWQ6cyxzcGFuX2lkOm4sc3RhdHVzOmksdHJhY2VfaWQ6ZSxvcmlnaW46Y30pfWZ1bmN0aW9uIGp0KHQpe3JldHVybiJudW1iZXIiPT10eXBlb2YgdD9SdCh0KTpBcnJheS5pc0FycmF5KHQpP3RbMF0rdFsxXS8xZTk6dCBpbnN0YW5jZW9mIERhdGU/UnQodC5nZXRUaW1lKCkpOlooKX1mdW5jdGlvbiBSdCh0KXtyZXR1cm4gdD45OTk5OTk5OTk5P3QvMWUzOnR9ZnVuY3Rpb24gQXQodCl7aWYoZnVuY3Rpb24odCl7cmV0dXJuImZ1bmN0aW9uIj09dHlwZW9mIHQuZ2V0U3BhbkpTT059KHQpKXJldHVybiB0LmdldFNwYW5KU09OKCk7dHJ5e2NvbnN0e3NwYW5JZDpuLHRyYWNlSWQ6ZX09dC5zcGFuQ29udGV4dCgpO2lmKGZ1bmN0aW9uKHQpe2NvbnN0IG49dDtyZXR1cm4hIShuLmF0dHJpYnV0ZXMmJm4uc3RhcnRUaW1lJiZuLm5hbWUmJm4uZW5kVGltZSYmbi5zdGF0dXMpfSh0KSl7Y29uc3R7YXR0cmlidXRlczpyLHN0YXJ0VGltZTpvLG5hbWU6cyxlbmRUaW1lOmkscGFyZW50U3BhbklkOmMsc3RhdHVzOnV9PXQ7cmV0dXJuIGooe3NwYW5faWQ6bix0cmFjZV9pZDplLGRhdGE6cixkZXNjcmlwdGlvbjpzLHBhcmVudF9zcGFuX2lkOmMsc3RhcnRfdGltZXN0YW1wOmp0KG8pLHRpbWVzdGFtcDpqdChpKXx8dm9pZCAwLHN0YXR1czpJdCh1KSxvcDpyW050XSxvcmlnaW46cltrdF0scTp2b2lkIDB9KX1yZXR1cm57c3Bhbl9pZDpuLHRyYWNlX2lkOmV9fWNhdGNoKHQpe3JldHVybnt9fX1mdW5jdGlvbiBJdCh0KXtpZih0JiZ0LmNvZGUhPT1DdClyZXR1cm4gdC5jb2RlPT09RHQ/Im9rIjp0Lm1lc3NhZ2V8fCJ1bmtub3duX2Vycm9yIn1jb25zdCBQdD0iX3NlbnRyeVJvb3RTcGFuIjtmdW5jdGlvbiBVdCh0KXtyZXR1cm4gdFtQdF18fHR9Y29uc3QgTXQ9InByb2R1Y3Rpb24iLEx0PSJfZnJvemVuRHNjIjtmdW5jdGlvbiBCdCh0KXtjb25zdCBuPXl0KCk7aWYoIW4pcmV0dXJue307Y29uc3QgZT1mdW5jdGlvbih0LG4pe2NvbnN0IGU9bi5nZXRPcHRpb25zKCkse3B1YmxpY0tleTpyfT1uLmdldERzbigpfHx7fSxvPWooe2Vudmlyb25tZW50OmUuZW52aXJvbm1lbnR8fE10LHJlbGVhc2U6ZS5yZWxlYXNlLHB1YmxpY19rZXk6cix0cmFjZV9pZDp0fSk7cmV0dXJuIG4uZW1pdCgiY3JlYXRlRHNjIixvKSxvfShBdCh0KS50cmFjZV9pZHx8IiIsbikscj1VdCh0KTtpZighcilyZXR1cm4gZTtjb25zdCBvPXJbTHRdO2lmKG8pcmV0dXJuIG87Y29uc3Qgcz1BdChyKSxpPXMuZGF0YXx8e30sYz1pW3h0XTtudWxsIT1jJiYoZS5zYW1wbGVfcmF0ZT1gJHtjfWApO2NvbnN0IHU9aVtFdF07cmV0dXJuIHUmJiJ1cmwiIT09dSYmKGUudHJhbnNhY3Rpb249cy5kZXNjcmlwdGlvbiksZS5zYW1wbGVkPVN0cmluZyhmdW5jdGlvbih0KXtjb25zdHt0cmFjZUZsYWdzOm59PXQuc3BhbkNvbnRleHQoKTtyZXR1cm4gbj09PVR0fShyKSksbi5lbWl0KCJjcmVhdGVEc2MiLGUpLGV9Y29uc3QgR3Q9Il9fU0VOVFJZX1NVUFBSRVNTX1RSQUNJTkdfXyI7ZnVuY3Rpb24gSnQodCl7Y29uc3Qgbj0kdCh1dCgpKTtyZXR1cm4gbi5zdXBwcmVzc1RyYWNpbmc/bi5zdXBwcmVzc1RyYWNpbmcodCk6ZnVuY3Rpb24oLi4udCl7Y29uc3Qgbj0kdCh1dCgpKTtpZigyPT09dC5sZW5ndGgpe2NvbnN0W2Uscl09dDtyZXR1cm4gZT9uLndpdGhTZXRTY29wZShlLHIpOm4ud2l0aFNjb3BlKHIpfXJldHVybiBuLndpdGhTY29wZSh0WzBdKX0oKG49PihuLnNldFNES1Byb2Nlc3NpbmdNZXRhZGF0YSh7W0d0XTohMH0pLHQoKSkpKX1mdW5jdGlvbiB6dCh0LG4sZSxyKXtjb25zdCBvPW90KGUpLHM9dC50eXBlJiYicmVwbGF5X2V2ZW50IiE9PXQudHlwZT90LnR5cGU6ImV2ZW50IjshZnVuY3Rpb24odCxuKXtuJiYodC5zZGs9dC5zZGt8fHt9LHQuc2RrLm5hbWU9dC5zZGsubmFtZXx8bi5uYW1lLHQuc2RrLnZlcnNpb249dC5zZGsudmVyc2lvbnx8bi52ZXJzaW9uLHQuc2RrLmludGVncmF0aW9ucz1bLi4udC5zZGsuaW50ZWdyYXRpb25zfHxbXSwuLi5uLmludGVncmF0aW9uc3x8W11dLHQuc2RrLnBhY2thZ2VzPVsuLi50LnNkay5wYWNrYWdlc3x8W10sLi4ubi5wYWNrYWdlc3x8W11dKX0odCxlJiZlLnNkayk7Y29uc3QgaT1mdW5jdGlvbih0LG4sZSxyKXtjb25zdCBvPXQuc2RrUHJvY2Vzc2luZ01ldGFkYXRhJiZ0LnNka1Byb2Nlc3NpbmdNZXRhZGF0YS5keW5hbWljU2FtcGxpbmdDb250ZXh0O3JldHVybntldmVudF9pZDp0LmV2ZW50X2lkLHNlbnRfYXQ6KG5ldyBEYXRlKS50b0lTT1N0cmluZygpLC4uLm4mJntzZGs6bn0sLi4uISFlJiZyJiZ7ZHNuOmsocil9LC4uLm8mJnt0cmFjZTpqKHsuLi5vfSl9fX0odCxvLHIsbik7ZGVsZXRlIHQuc2RrUHJvY2Vzc2luZ01ldGFkYXRhO3JldHVybiBRKGksW1t7dHlwZTpzfSx0XV0pfWZ1bmN0aW9uIEh0KHQsbil7Y29uc3R7ZmluZ2VycHJpbnQ6ZSxzcGFuOnIsYnJlYWRjcnVtYnM6byxzZGtQcm9jZXNzaW5nTWV0YWRhdGE6c309bjshZnVuY3Rpb24odCxuKXtjb25zdHtleHRyYTplLHRhZ3M6cix1c2VyOm8sY29udGV4dHM6cyxsZXZlbDppLHRyYW5zYWN0aW9uTmFtZTpjfT1uLHU9aihlKTt1JiZPYmplY3Qua2V5cyh1KS5sZW5ndGgmJih0LmV4dHJhPXsuLi51LC4uLnQuZXh0cmF9KTtjb25zdCBhPWoocik7YSYmT2JqZWN0LmtleXMoYSkubGVuZ3RoJiYodC50YWdzPXsuLi5hLC4uLnQudGFnc30pO2NvbnN0IGY9aihvKTtmJiZPYmplY3Qua2V5cyhmKS5sZW5ndGgmJih0LnVzZXI9ey4uLmYsLi4udC51c2VyfSk7Y29uc3QgaD1qKHMpO2gmJk9iamVjdC5rZXlzKGgpLmxlbmd0aCYmKHQuY29udGV4dHM9ey4uLmgsLi4udC5jb250ZXh0c30pO2kmJih0LmxldmVsPWkpO2MmJiJ0cmFuc2FjdGlvbiIhPT10LnR5cGUmJih0LnRyYW5zYWN0aW9uPWMpfSh0LG4pLHImJmZ1bmN0aW9uKHQsbil7dC5jb250ZXh0cz17dHJhY2U6T3QobiksLi4udC5jb250ZXh0c30sdC5zZGtQcm9jZXNzaW5nTWV0YWRhdGE9e2R5bmFtaWNTYW1wbGluZ0NvbnRleHQ6QnQobiksLi4udC5zZGtQcm9jZXNzaW5nTWV0YWRhdGF9O2NvbnN0IGU9VXQobikscj1BdChlKS5kZXNjcmlwdGlvbjtyJiYhdC50cmFuc2FjdGlvbiYmInRyYW5zYWN0aW9uIj09PXQudHlwZSYmKHQudHJhbnNhY3Rpb249cil9KHQsciksZnVuY3Rpb24odCxuKXt0LmZpbmdlcnByaW50PXQuZmluZ2VycHJpbnQ/ZnVuY3Rpb24odCl7cmV0dXJuIEFycmF5LmlzQXJyYXkodCk/dDpbdF19KHQuZmluZ2VycHJpbnQpOltdLG4mJih0LmZpbmdlcnByaW50PXQuZmluZ2VycHJpbnQuY29uY2F0KG4pKTt0LmZpbmdlcnByaW50JiYhdC5maW5nZXJwcmludC5sZW5ndGgmJmRlbGV0ZSB0LmZpbmdlcnByaW50fSh0LGUpLGZ1bmN0aW9uKHQsbil7Y29uc3QgZT1bLi4udC5icmVhZGNydW1ic3x8W10sLi4ubl07dC5icmVhZGNydW1icz1lLmxlbmd0aD9lOnZvaWQgMH0odCxvKSxmdW5jdGlvbih0LG4pe3Quc2RrUHJvY2Vzc2luZ01ldGFkYXRhPXsuLi50LnNka1Byb2Nlc3NpbmdNZXRhZGF0YSwuLi5ufX0odCxzKX1jb25zdCBXdD0iNyI7ZnVuY3Rpb24gWXQodCxuKXtyZXR1cm4gZT17c2VudHJ5X2tleTp0LnB1YmxpY0tleSxzZW50cnlfdmVyc2lvbjpXdCwuLi5uJiZ7c2VudHJ5X2NsaWVudDpgJHtuLm5hbWV9LyR7bi52ZXJzaW9ufWB9fSxPYmplY3Qua2V5cyhlKS5tYXAoKHQ9PmAke2VuY29kZVVSSUNvbXBvbmVudCh0KX09JHtlbmNvZGVVUklDb21wb25lbnQoZVt0XSl9YCkpLmpvaW4oIiYiKTt2YXIgZX1jb25zdCBxdD0zMDtmdW5jdGlvbiBGdCh0LG4sZT1xKHQuYnVmZmVyU2l6ZXx8cXQpKXtsZXQgcj17fTtyZXR1cm57c2VuZDpmdW5jdGlvbihvKXtjb25zdCBzPVtdO2lmKFgobywoKG4sZSk9Pntjb25zdCBvPXJ0KGUpO2lmKGZ1bmN0aW9uKHQsbixlPURhdGUubm93KCkpe3JldHVybiBmdW5jdGlvbih0LG4pe3JldHVybiB0W25dfHx0LmFsbHx8MH0odCxuKT5lfShyLG8pKXtjb25zdCByPUt0KG4sZSk7dC5yZWNvcmREcm9wcGVkRXZlbnQoInJhdGVsaW1pdF9iYWNrb2ZmIixvLHIpfWVsc2Ugcy5wdXNoKG4pfSkpLDA9PT1zLmxlbmd0aClyZXR1cm4gVyh7fSk7Y29uc3QgaT1RKG9bMF0scyksYz1uPT57WChpLCgoZSxyKT0+e2NvbnN0IG89S3QoZSxyKTt0LnJlY29yZERyb3BwZWRFdmVudChuLHJ0KHIpLG8pfSkpfTtyZXR1cm4gZS5hZGQoKCgpPT5uKHtib2R5Om50KGkpfSkudGhlbigodD0+KHZvaWQgMCE9PXQuc3RhdHVzQ29kZSYmKHQuc3RhdHVzQ29kZTwyMDB8fHQuc3RhdHVzQ29kZT49MzAwKSYmY3QmJk4ud2FybihgU2VudHJ5IHJlc3BvbmRlZCB3aXRoIHN0YXR1cyBjb2RlICR7dC5zdGF0dXNDb2RlfSB0byBzZW50IGV2ZW50LmApLHI9aXQocix0KSx0KSksKHQ9Pnt0aHJvdyBjKCJuZXR3b3JrX2Vycm9yIiksdH0pKSkpLnRoZW4oKHQ9PnQpLCh0PT57aWYodCBpbnN0YW5jZW9mIEMpcmV0dXJuIGN0JiZOLmVycm9yKCJTa2lwcGVkIHNlbmRpbmcgZXZlbnQgYmVjYXVzZSBidWZmZXIgaXMgZnVsbC4iKSxjKCJxdWV1ZV9vdmVyZmxvdyIpLFcoe30pO3Rocm93IHR9KSl9LGZsdXNoOnQ9PmUuZHJhaW4odCl9fWZ1bmN0aW9uIEt0KHQsbil7aWYoImV2ZW50Ij09PW58fCJ0cmFuc2FjdGlvbiI9PT1uKXJldHVybiBBcnJheS5pc0FycmF5KHQpP3RbMV06dm9pZCAwfWNvbnN0IFZ0PVN5bWJvbCgiQWdlbnRCYXNlSW50ZXJuYWxTdGF0ZSIpO2NsYXNzIFp0IGV4dGVuZHMgaC5BZ2VudHtbVnRdO29wdGlvbnM7a2VlcEFsaXZlO2NvbnN0cnVjdG9yKHQpe3N1cGVyKHQpLHRoaXNbVnRdPXt9fWlzU2VjdXJlRW5kcG9pbnQodCl7aWYodCl7aWYoImJvb2xlYW4iPT10eXBlb2YgdC5zZWN1cmVFbmRwb2ludClyZXR1cm4gdC5zZWN1cmVFbmRwb2ludDtpZigic3RyaW5nIj09dHlwZW9mIHQucHJvdG9jb2wpcmV0dXJuImh0dHBzOiI9PT10LnByb3RvY29sfWNvbnN0e3N0YWNrOm59PW5ldyBFcnJvcjtyZXR1cm4ic3RyaW5nIj09dHlwZW9mIG4mJm4uc3BsaXQoIlxuIikuc29tZSgodD0+LTEhPT10LmluZGV4T2YoIihodHRwcy5qczoiKXx8LTEhPT10LmluZGV4T2YoIm5vZGU6aHR0cHM6IikpKX1jcmVhdGVTb2NrZXQodCxuLGUpe2NvbnN0IHI9ey4uLm4sc2VjdXJlRW5kcG9pbnQ6dGhpcy5pc1NlY3VyZUVuZHBvaW50KG4pfTtQcm9taXNlLnJlc29sdmUoKS50aGVuKCgoKT0+dGhpcy5jb25uZWN0KHQscikpKS50aGVuKChvPT57aWYobyBpbnN0YW5jZW9mIGguQWdlbnQpcmV0dXJuIG8uYWRkUmVxdWVzdCh0LHIpO3RoaXNbVnRdLmN1cnJlbnRTb2NrZXQ9byxzdXBlci5jcmVhdGVTb2NrZXQodCxuLGUpfSksZSl9Y3JlYXRlQ29ubmVjdGlvbigpe2NvbnN0IHQ9dGhpc1tWdF0uY3VycmVudFNvY2tldDtpZih0aGlzW1Z0XS5jdXJyZW50U29ja2V0PXZvaWQgMCwhdCl0aHJvdyBuZXcgRXJyb3IoIk5vIHNvY2tldCB3YXMgcmV0dXJuZWQgaW4gdGhlIGBjb25uZWN0KClgIGZ1bmN0aW9uIik7cmV0dXJuIHR9Z2V0IGRlZmF1bHRQb3J0KCl7cmV0dXJuIHRoaXNbVnRdLmRlZmF1bHRQb3J0Pz8oImh0dHBzOiI9PT10aGlzLnByb3RvY29sPzQ0Mzo4MCl9c2V0IGRlZmF1bHRQb3J0KHQpe3RoaXNbVnRdJiYodGhpc1tWdF0uZGVmYXVsdFBvcnQ9dCl9Z2V0IHByb3RvY29sKCl7cmV0dXJuIHRoaXNbVnRdLnByb3RvY29sPz8odGhpcy5pc1NlY3VyZUVuZHBvaW50KCk/Imh0dHBzOiI6Imh0dHA6Iil9c2V0IHByb3RvY29sKHQpe3RoaXNbVnRdJiYodGhpc1tWdF0ucHJvdG9jb2w9dCl9fWZ1bmN0aW9uIFF0KC4uLnQpe04ubG9nKCJbaHR0cHMtcHJveHktYWdlbnQ6cGFyc2UtcHJveHktcmVzcG9uc2VdIiwuLi50KX1mdW5jdGlvbiBYdCh0KXtyZXR1cm4gbmV3IFByb21pc2UoKChuLGUpPT57bGV0IHI9MDtjb25zdCBvPVtdO2Z1bmN0aW9uIHMoKXtjb25zdCBjPXQucmVhZCgpO2M/ZnVuY3Rpb24oYyl7by5wdXNoKGMpLHIrPWMubGVuZ3RoO2NvbnN0IHU9QnVmZmVyLmNvbmNhdChvLHIpLGE9dS5pbmRleE9mKCJcclxuXHJcbiIpO2lmKC0xPT09YSlyZXR1cm4gUXQoImhhdmUgbm90IHJlY2VpdmVkIGVuZCBvZiBIVFRQIGhlYWRlcnMgeWV0Li4uIiksdm9pZCBzKCk7Y29uc3QgZj11LnNsaWNlKDAsYSkudG9TdHJpbmcoImFzY2lpIikuc3BsaXQoIlxyXG4iKSxoPWYuc2hpZnQoKTtpZighaClyZXR1cm4gdC5kZXN0cm95KCksZShuZXcgRXJyb3IoIk5vIGhlYWRlciByZWNlaXZlZCBmcm9tIHByb3h5IENPTk5FQ1QgcmVzcG9uc2UiKSk7Y29uc3QgcD1oLnNwbGl0KCIgIiksbD0rcFsxXSxkPXAuc2xpY2UoMikuam9pbigiICIpLG09e307Zm9yKGNvbnN0IG4gb2YgZil7aWYoIW4pY29udGludWU7Y29uc3Qgcj1uLmluZGV4T2YoIjoiKTtpZigtMT09PXIpcmV0dXJuIHQuZGVzdHJveSgpLGUobmV3IEVycm9yKGBJbnZhbGlkIGhlYWRlciBmcm9tIHByb3h5IENPTk5FQ1QgcmVzcG9uc2U6ICIke259ImApKTtjb25zdCBvPW4uc2xpY2UoMCxyKS50b0xvd2VyQ2FzZSgpLHM9bi5zbGljZShyKzEpLnRyaW1TdGFydCgpLGk9bVtvXTsic3RyaW5nIj09dHlwZW9mIGk/bVtvXT1baSxzXTpBcnJheS5pc0FycmF5KGkpP2kucHVzaChzKTptW29dPXN9UXQoImdvdCBwcm94eSBzZXJ2ZXIgcmVzcG9uc2U6ICVvICVvIixoLG0pLGkoKSxuKHtjb25uZWN0OntzdGF0dXNDb2RlOmwsc3RhdHVzVGV4dDpkLGhlYWRlcnM6bX0sYnVmZmVyZWQ6dX0pfShjKTp0Lm9uY2UoInJlYWRhYmxlIixzKX1mdW5jdGlvbiBpKCl7dC5yZW1vdmVMaXN0ZW5lcigiZW5kIixjKSx0LnJlbW92ZUxpc3RlbmVyKCJlcnJvciIsdSksdC5yZW1vdmVMaXN0ZW5lcigicmVhZGFibGUiLHMpfWZ1bmN0aW9uIGMoKXtpKCksUXQoIm9uZW5kIiksZShuZXcgRXJyb3IoIlByb3h5IGNvbm5lY3Rpb24gZW5kZWQgYmVmb3JlIHJlY2VpdmluZyBDT05ORUNUIHJlc3BvbnNlIikpfWZ1bmN0aW9uIHUodCl7aSgpLFF0KCJvbmVycm9yICVvIix0KSxlKHQpfXQub24oImVycm9yIix1KSx0Lm9uKCJlbmQiLGMpLHMoKX0pKX1mdW5jdGlvbiB0biguLi50KXtOLmxvZygiW2h0dHBzLXByb3h5LWFnZW50XSIsLi4udCl9Y2xhc3Mgbm4gZXh0ZW5kcyBadHtzdGF0aWMgcHJvdG9jb2xzPVsiaHR0cCIsImh0dHBzIl07cHJveHk7cHJveHlIZWFkZXJzO2Nvbm5lY3RPcHRzO2NvbnN0cnVjdG9yKHQsbil7c3VwZXIobiksdGhpcy5vcHRpb25zPXt9LHRoaXMucHJveHk9InN0cmluZyI9PXR5cGVvZiB0P25ldyBVUkwodCk6dCx0aGlzLnByb3h5SGVhZGVycz1uPy5oZWFkZXJzPz97fSx0bigiQ3JlYXRpbmcgbmV3IEh0dHBzUHJveHlBZ2VudCBpbnN0YW5jZTogJW8iLHRoaXMucHJveHkuaHJlZik7Y29uc3QgZT0odGhpcy5wcm94eS5ob3N0bmFtZXx8dGhpcy5wcm94eS5ob3N0KS5yZXBsYWNlKC9eXFt8XF0kL2csIiIpLHI9dGhpcy5wcm94eS5wb3J0P3BhcnNlSW50KHRoaXMucHJveHkucG9ydCwxMCk6Imh0dHBzOiI9PT10aGlzLnByb3h5LnByb3RvY29sPzQ0Mzo4MDt0aGlzLmNvbm5lY3RPcHRzPXtBTFBOUHJvdG9jb2xzOlsiaHR0cC8xLjEiXSwuLi5uP3JuKG4sImhlYWRlcnMiKTpudWxsLGhvc3Q6ZSxwb3J0OnJ9fWFzeW5jIGNvbm5lY3QodCxuKXtjb25zdHtwcm94eTplfT10aGlzO2lmKCFuLmhvc3QpdGhyb3cgbmV3IFR5cGVFcnJvcignTm8gImhvc3QiIHByb3ZpZGVkJyk7bGV0IHI7aWYoImh0dHBzOiI9PT1lLnByb3RvY29sKXt0bigiQ3JlYXRpbmcgYHRscy5Tb2NrZXRgOiAlbyIsdGhpcy5jb25uZWN0T3B0cyk7Y29uc3QgdD10aGlzLmNvbm5lY3RPcHRzLnNlcnZlcm5hbWV8fHRoaXMuY29ubmVjdE9wdHMuaG9zdDtyPWYuY29ubmVjdCh7Li4udGhpcy5jb25uZWN0T3B0cyxzZXJ2ZXJuYW1lOnQmJmEuaXNJUCh0KT92b2lkIDA6dH0pfWVsc2UgdG4oIkNyZWF0aW5nIGBuZXQuU29ja2V0YDogJW8iLHRoaXMuY29ubmVjdE9wdHMpLHI9YS5jb25uZWN0KHRoaXMuY29ubmVjdE9wdHMpO2NvbnN0IG89ImZ1bmN0aW9uIj09dHlwZW9mIHRoaXMucHJveHlIZWFkZXJzP3RoaXMucHJveHlIZWFkZXJzKCk6ey4uLnRoaXMucHJveHlIZWFkZXJzfSxzPWEuaXNJUHY2KG4uaG9zdCk/YFske24uaG9zdH1dYDpuLmhvc3Q7bGV0IGk9YENPTk5FQ1QgJHtzfToke24ucG9ydH0gSFRUUC8xLjFcclxuYDtpZihlLnVzZXJuYW1lfHxlLnBhc3N3b3JkKXtjb25zdCB0PWAke2RlY29kZVVSSUNvbXBvbmVudChlLnVzZXJuYW1lKX06JHtkZWNvZGVVUklDb21wb25lbnQoZS5wYXNzd29yZCl9YDtvWyJQcm94eS1BdXRob3JpemF0aW9uIl09YEJhc2ljICR7QnVmZmVyLmZyb20odCkudG9TdHJpbmcoImJhc2U2NCIpfWB9by5Ib3N0PWAke3N9OiR7bi5wb3J0fWAsb1siUHJveHktQ29ubmVjdGlvbiJdfHwob1siUHJveHktQ29ubmVjdGlvbiJdPXRoaXMua2VlcEFsaXZlPyJLZWVwLUFsaXZlIjoiY2xvc2UiKTtmb3IoY29uc3QgdCBvZiBPYmplY3Qua2V5cyhvKSlpKz1gJHt0fTogJHtvW3RdfVxyXG5gO2NvbnN0IGM9WHQocik7ci53cml0ZShgJHtpfVxyXG5gKTtjb25zdHtjb25uZWN0OnUsYnVmZmVyZWQ6aH09YXdhaXQgYztpZih0LmVtaXQoInByb3h5Q29ubmVjdCIsdSksdGhpcy5lbWl0KCJwcm94eUNvbm5lY3QiLHUsdCksMjAwPT09dS5zdGF0dXNDb2RlKXtpZih0Lm9uY2UoInNvY2tldCIsZW4pLG4uc2VjdXJlRW5kcG9pbnQpe3RuKCJVcGdyYWRpbmcgc29ja2V0IGNvbm5lY3Rpb24gdG8gVExTIik7Y29uc3QgdD1uLnNlcnZlcm5hbWV8fG4uaG9zdDtyZXR1cm4gZi5jb25uZWN0KHsuLi5ybihuLCJob3N0IiwicGF0aCIsInBvcnQiKSxzb2NrZXQ6cixzZXJ2ZXJuYW1lOmEuaXNJUCh0KT92b2lkIDA6dH0pfXJldHVybiByfXIuZGVzdHJveSgpO2NvbnN0IHA9bmV3IGEuU29ja2V0KHt3cml0YWJsZTohMX0pO3JldHVybiBwLnJlYWRhYmxlPSEwLHQub25jZSgic29ja2V0IiwodD0+e3RuKCJSZXBsYXlpbmcgcHJveHkgYnVmZmVyIGZvciBmYWlsZWQgcmVxdWVzdCIpLHQucHVzaChoKSx0LnB1c2gobnVsbCl9KSkscH19ZnVuY3Rpb24gZW4odCl7dC5yZXN1bWUoKX1mdW5jdGlvbiBybih0LC4uLm4pe2NvbnN0IGU9e307bGV0IHI7Zm9yKHIgaW4gdCluLmluY2x1ZGVzKHIpfHwoZVtyXT10W3JdKTtyZXR1cm4gZX1jb25zdCBvbj0zMjc2ODtmdW5jdGlvbiBzbih0KXtyZXR1cm4gdC5yZXBsYWNlKC9eW0EtWl06LywiIikucmVwbGFjZSgvXFwvZywiLyIpfWNvbnN0IGNuPWU7bGV0IHVuLGFuPSExO2Z1bmN0aW9uIGZuKHQpe2NuLmRlYnVnJiZjb25zb2xlLmxvZyhgW0FOUiBXb3JrZXJdICR7dH1gKX12YXIgaG4scG4sbG47Y29uc3QgZG49ZnVuY3Rpb24odCl7bGV0IG47dHJ5e249bmV3IFVSTCh0LnVybCl9Y2F0Y2gobil7cmV0dXJuIHgoKCgpPT57Y29uc29sZS53YXJuKCJbQHNlbnRyeS9ub2RlXTogSW52YWxpZCBkc24gb3IgdHVubmVsIG9wdGlvbiwgd2lsbCBub3Qgc2VuZCBhbnkgZXZlbnRzLiBUaGUgdHVubmVsIG9wdGlvbiBtdXN0IGJlIGEgZnVsbCBVUkwgd2hlbiB1c2VkLiIpfSkpLEZ0KHQsKCgpPT5Qcm9taXNlLnJlc29sdmUoe30pKSl9Y29uc3QgZT0iaHR0cHM6Ij09PW4ucHJvdG9jb2wscj1mdW5jdGlvbih0LG4pe2NvbnN0e25vX3Byb3h5OmV9PXByb2Nlc3MuZW52O3JldHVybiBlJiZlLnNwbGl0KCIsIikuc29tZSgobj0+dC5ob3N0LmVuZHNXaXRoKG4pfHx0Lmhvc3RuYW1lLmVuZHNXaXRoKG4pKSk/dm9pZCAwOm59KG4sdC5wcm94eXx8KGU/cHJvY2Vzcy5lbnYuaHR0cHNfcHJveHk6dm9pZCAwKXx8cHJvY2Vzcy5lbnYuaHR0cF9wcm94eSksbz1lP2k6cyxhPXZvaWQgMCE9PXQua2VlcEFsaXZlJiZ0LmtlZXBBbGl2ZSxmPXI/bmV3IG5uKHIpOm5ldyBvLkFnZW50KHtrZWVwQWxpdmU6YSxtYXhTb2NrZXRzOjMwLHRpbWVvdXQ6MmUzfSk7cmV0dXJuIEp0KCgoKT0+e2NvbnN0IG49ZnVuY3Rpb24odCxuLGUpe2NvbnN0e2hvc3RuYW1lOnIscGF0aG5hbWU6byxwb3J0OnMscHJvdG9jb2w6aSxzZWFyY2g6YX09bmV3IFVSTCh0LnVybCk7cmV0dXJuIGZ1bmN0aW9uKGYpe3JldHVybiBuZXcgUHJvbWlzZSgoKGgscCk9PntsZXQgbD1mdW5jdGlvbih0KXtyZXR1cm4gbmV3IGMoe3JlYWQoKXt0aGlzLnB1c2godCksdGhpcy5wdXNoKG51bGwpfX0pfShmLmJvZHkpO2NvbnN0IGQ9ey4uLnQuaGVhZGVyc307Zi5ib2R5Lmxlbmd0aD5vbiYmKGRbImNvbnRlbnQtZW5jb2RpbmciXT0iZ3ppcCIsbD1sLnBpcGUodSgpKSk7Y29uc3QgbT1uLnJlcXVlc3Qoe21ldGhvZDoiUE9TVCIsYWdlbnQ6ZSxoZWFkZXJzOmQsaG9zdG5hbWU6cixwYXRoOmAke299JHthfWAscG9ydDpzLHByb3RvY29sOmksY2E6dC5jYUNlcnRzfSwodD0+e3Qub24oImRhdGEiLCgoKT0+e30pKSx0Lm9uKCJlbmQiLCgoKT0+e30pKSx0LnNldEVuY29kaW5nKCJ1dGY4Iik7Y29uc3Qgbj10LmhlYWRlcnNbInJldHJ5LWFmdGVyIl0/P251bGwsZT10LmhlYWRlcnNbIngtc2VudHJ5LXJhdGUtbGltaXRzIl0/P251bGw7aCh7c3RhdHVzQ29kZTp0LnN0YXR1c0NvZGUsaGVhZGVyczp7InJldHJ5LWFmdGVyIjpuLCJ4LXNlbnRyeS1yYXRlLWxpbWl0cyI6QXJyYXkuaXNBcnJheShlKT9lWzBdOmV9fSl9KSk7bS5vbigiZXJyb3IiLHApLGwucGlwZShtKX0pKX19KHQsdC5odHRwTW9kdWxlPz9vLGYpO3JldHVybiBGdCh0LG4pfSkpfSh7dXJsOihobj1jbi5kc24scG49Y24udHVubmVsLGxuPWNuLnNka01ldGFkYXRhLnNkayxwbnx8YCR7ZnVuY3Rpb24odCl7cmV0dXJuYCR7ZnVuY3Rpb24odCl7Y29uc3Qgbj10LnByb3RvY29sP2Ake3QucHJvdG9jb2x9OmA6IiIsZT10LnBvcnQ/YDoke3QucG9ydH1gOiIiO3JldHVybmAke259Ly8ke3QuaG9zdH0ke2V9JHt0LnBhdGg/YC8ke3QucGF0aH1gOiIifS9hcGkvYH0odCl9JHt0LnByb2plY3RJZH0vZW52ZWxvcGUvYH0oaG4pfT8ke1l0KGhuLGxuKX1gKSxyZWNvcmREcm9wcGVkRXZlbnQ6KCk9Pnt9fSk7YXN5bmMgZnVuY3Rpb24gbW4oKXtpZih1bil7Zm4oIlNlbmRpbmcgYWJub3JtYWwgc2Vzc2lvbiIpLGh0KHVuLHtzdGF0dXM6ImFibm9ybWFsIixhYm5vcm1hbF9tZWNoYW5pc206ImFucl9mb3JlZ3JvdW5kIn0pO2NvbnN0IHQ9ZnVuY3Rpb24odCxuLGUscil7Y29uc3Qgbz1vdChlKTtyZXR1cm4gUSh7c2VudF9hdDoobmV3IERhdGUpLnRvSVNPU3RyaW5nKCksLi4ubyYme3NkazpvfSwuLi4hIXImJm4mJntkc246ayhuKX19LFsiYWdncmVnYXRlcyJpbiB0P1t7dHlwZToic2Vzc2lvbnMifSx0XTpbe3R5cGU6InNlc3Npb24ifSx0LnRvSlNPTigpXV0pfSh1bixjbi5kc24sY24uc2RrTWV0YWRhdGEsY24udHVubmVsKTtmbihKU09OLnN0cmluZ2lmeSh0KSksYXdhaXQgZG4uc2VuZCh0KTt0cnl7bj8ucG9zdE1lc3NhZ2UoInNlc3Npb24tZW5kZWQiKX1jYXRjaCh0KXt9fX1mdW5jdGlvbiBnbih0KXtpZighdClyZXR1cm47Y29uc3Qgbj1mdW5jdGlvbih0KXtpZighdC5sZW5ndGgpcmV0dXJuW107Y29uc3Qgbj1BcnJheS5mcm9tKHQpO3JldHVybi9zZW50cnlXcmFwcGVkLy50ZXN0KG5bbi5sZW5ndGgtMV0uZnVuY3Rpb258fCIiKSYmbi5wb3AoKSxuLnJldmVyc2UoKSxQLnRlc3QobltuLmxlbmd0aC0xXS5mdW5jdGlvbnx8IiIpJiYobi5wb3AoKSxQLnRlc3QobltuLmxlbmd0aC0xXS5mdW5jdGlvbnx8IiIpJiZuLnBvcCgpKSxuLnNsaWNlKDAsQSkubWFwKCh0PT4oey4uLnQsZmlsZW5hbWU6dC5maWxlbmFtZXx8bltuLmxlbmd0aC0xXS5maWxlbmFtZSxmdW5jdGlvbjp0LmZ1bmN0aW9ufHxJfSkpKX0odCk7aWYoY24uYXBwUm9vdFBhdGgpZm9yKGNvbnN0IHQgb2Ygbil0LmZpbGVuYW1lJiYodC5maWxlbmFtZT1HKHQuZmlsZW5hbWUsY24uYXBwUm9vdFBhdGgpKTtyZXR1cm4gbn1hc3luYyBmdW5jdGlvbiB5bih0LG4pe2lmKGFuKXJldHVybjthbj0hMCxhd2FpdCBtbigpLGZuKCJTZW5kaW5nIGV2ZW50Iik7Y29uc3QgZT17ZXZlbnRfaWQ6TSgpLGNvbnRleHRzOmNuLmNvbnRleHRzLHJlbGVhc2U6Y24ucmVsZWFzZSxlbnZpcm9ubWVudDpjbi5lbnZpcm9ubWVudCxkaXN0OmNuLmRpc3QscGxhdGZvcm06Im5vZGUiLGxldmVsOiJlcnJvciIsZXhjZXB0aW9uOnt2YWx1ZXM6W3t0eXBlOiJBcHBsaWNhdGlvbk5vdFJlc3BvbmRpbmciLHZhbHVlOmBBcHBsaWNhdGlvbiBOb3QgUmVzcG9uZGluZyBmb3IgYXQgbGVhc3QgJHtjbi5hbnJUaHJlc2hvbGR9IG1zYCxzdGFja3RyYWNlOntmcmFtZXM6Z24odCl9LG1lY2hhbmlzbTp7dHlwZToiQU5SIn19XX0sdGFnczpjbi5zdGF0aWNUYWdzfTtuJiZmdW5jdGlvbih0LG4pe2lmKEh0KHQsbiksIXQuY29udGV4dHM/LnRyYWNlKXtjb25zdHt0cmFjZUlkOmUsc3BhbklkOnIscGFyZW50U3BhbklkOm99PW4ucHJvcGFnYXRpb25Db250ZXh0O3QuY29udGV4dHM9e3RyYWNlOnt0cmFjZV9pZDplLHNwYW5faWQ6cixwYXJlbnRfc3Bhbl9pZDpvfSwuLi50LmNvbnRleHRzfX19KGUsbik7Y29uc3Qgcj16dChlLGNuLmRzbixjbi5zZGtNZXRhZGF0YSxjbi50dW5uZWwpO2ZuKEpTT04uc3RyaW5naWZ5KHIpKSxhd2FpdCBkbi5zZW5kKHIpLGF3YWl0IGRuLmZsdXNoKDJlMyksc2V0VGltZW91dCgoKCk9Pntwcm9jZXNzLmV4aXQoMCl9KSw1ZTMpfWxldCBibjtpZihmbigiU3RhcnRlZCIpLGNuLmNhcHR1cmVTdGFja1RyYWNlKXtmbigiQ29ubmVjdGluZyB0byBkZWJ1Z2dlciIpO2NvbnN0IG49bmV3IHQ7bi5jb25uZWN0VG9NYWluVGhyZWFkKCksZm4oIkNvbm5lY3RlZCB0byBkZWJ1Z2dlciIpO2NvbnN0IGU9bmV3IE1hcDtuLm9uKCJEZWJ1Z2dlci5zY3JpcHRQYXJzZWQiLCh0PT57ZS5zZXQodC5wYXJhbXMuc2NyaXB0SWQsdC5wYXJhbXMudXJsKX0pKSxuLm9uKCJEZWJ1Z2dlci5wYXVzZWQiLCh0PT57aWYoIm90aGVyIj09PXQucGFyYW1zLnJlYXNvbil0cnl7Zm4oIkRlYnVnZ2VyIHBhdXNlZCIpO2NvbnN0IHM9Wy4uLnQucGFyYW1zLmNhbGxGcmFtZXNdLGk9Y24uYXBwUm9vdFBhdGg/ZnVuY3Rpb24odD0ocHJvY2Vzcy5hcmd2WzFdP3oocHJvY2Vzcy5hcmd2WzFdKTpwcm9jZXNzLmN3ZCgpKSxuPSJcXCI9PT1vKXtjb25zdCBlPW4/c24odCk6dDtyZXR1cm4gdD0+e2lmKCF0KXJldHVybjtjb25zdCBvPW4/c24odCk6dDtsZXR7ZGlyOnMsYmFzZTppLGV4dDpjfT1yLnBhcnNlKG8pOyIuanMiIT09YyYmIi5tanMiIT09YyYmIi5janMiIT09Y3x8KGk9aS5zbGljZSgwLC0xKmMubGVuZ3RoKSksc3x8KHM9Ii4iKTtjb25zdCB1PXMubGFzdEluZGV4T2YoIi9ub2RlX21vZHVsZXMiKTtpZih1Pi0xKXJldHVybmAke3Muc2xpY2UodSsxNCkucmVwbGFjZSgvXC8vZywiLiIpfToke2l9YDtpZihzLnN0YXJ0c1dpdGgoZSkpe2xldCB0PXMuc2xpY2UoZS5sZW5ndGgrMSkucmVwbGFjZSgvXC8vZywiLiIpO3JldHVybiB0JiYodCs9IjoiKSx0Kz1pLHR9cmV0dXJuIGl9fShjbi5hcHBSb290UGF0aCk6KCk9Pnt9LGM9cy5tYXAoKHQ9PmZ1bmN0aW9uKHQsbixlKXtjb25zdCByPW4/bi5yZXBsYWNlKC9eZmlsZTpcL1wvLywiIik6dm9pZCAwLG89dC5sb2NhdGlvbi5jb2x1bW5OdW1iZXI/dC5sb2NhdGlvbi5jb2x1bW5OdW1iZXIrMTp2b2lkIDAscz10LmxvY2F0aW9uLmxpbmVOdW1iZXI/dC5sb2NhdGlvbi5saW5lTnVtYmVyKzE6dm9pZCAwO3JldHVybiBqKHtmaWxlbmFtZTpyLG1vZHVsZTplKHIpLGZ1bmN0aW9uOnQuZnVuY3Rpb25OYW1lfHxJLGNvbG5vOm8sbGluZW5vOnMsaW5fYXBwOnI/RihyKTp2b2lkIDB9KX0odCxlLmdldCh0LmxvY2F0aW9uLnNjcmlwdElkKSxpKSkpLHU9c2V0VGltZW91dCgoKCk9Pnt5bihjKS50aGVuKG51bGwsKCgpPT57Zm4oIlNlbmRpbmcgQU5SIGV2ZW50IGZhaWxlZC4iKX0pKX0pLDVlMyk7bi5wb3N0KCJSdW50aW1lLmV2YWx1YXRlIix7ZXhwcmVzc2lvbjoiZ2xvYmFsLl9fU0VOVFJZX0dFVF9TQ09QRVNfXygpOyIsc2lsZW50OiEwLHJldHVybkJ5VmFsdWU6ITB9LCgodCxlKT0+e3QmJmZuKGBFcnJvciBleGVjdXRpbmcgc2NyaXB0OiAnJHt0Lm1lc3NhZ2V9J2ApLGNsZWFyVGltZW91dCh1KTtjb25zdCByPWUmJmUucmVzdWx0P2UucmVzdWx0LnZhbHVlOnZvaWQgMDtuLnBvc3QoIkRlYnVnZ2VyLnJlc3VtZSIpLG4ucG9zdCgiRGVidWdnZXIuZGlzYWJsZSIpLHluKGMscikudGhlbihudWxsLCgoKT0+e2ZuKCJTZW5kaW5nIEFOUiBldmVudCBmYWlsZWQuIil9KSl9KSl9Y2F0Y2godCl7dGhyb3cgbi5wb3N0KCJEZWJ1Z2dlci5yZXN1bWUiKSxuLnBvc3QoIkRlYnVnZ2VyLmRpc2FibGUiKSx0fX0pKSxibj0oKT0+e3RyeXtuLnBvc3QoIkRlYnVnZ2VyLmVuYWJsZSIsKCgpPT57bi5wb3N0KCJEZWJ1Z2dlci5wYXVzZSIpfSkpfWNhdGNoKHQpe319fWNvbnN0e3BvbGw6dm59PWZ1bmN0aW9uKHQsbixlLHIpe2NvbnN0IG89dCgpO2xldCBzPSExLGk9ITA7cmV0dXJuIHNldEludGVydmFsKCgoKT0+e2NvbnN0IHQ9by5nZXRUaW1lTXMoKTshMT09PXMmJnQ+bitlJiYocz0hMCxpJiZyKCkpLHQ8bitlJiYocz0hMSl9KSwyMCkse3BvbGw6KCk9PntvLnJlc2V0KCl9LGVuYWJsZWQ6dD0+e2k9dH19fSgoZnVuY3Rpb24oKXtsZXQgdD1wcm9jZXNzLmhydGltZSgpO3JldHVybntnZXRUaW1lTXM6KCk9Pntjb25zdFtuLGVdPXByb2Nlc3MuaHJ0aW1lKHQpO3JldHVybiBNYXRoLmZsb29yKDFlMypuK2UvMWU2KX0scmVzZXQ6KCk9Pnt0PXByb2Nlc3MuaHJ0aW1lKCl9fX0pLGNuLnBvbGxJbnRlcnZhbCxjbi5hbnJUaHJlc2hvbGQsKGZ1bmN0aW9uKCl7Zm4oIldhdGNoZG9nIHRpbWVvdXQiKSxibj8oZm4oIlBhdXNpbmcgZGVidWdnZXIgdG8gY2FwdHVyZSBzdGFjayB0cmFjZSIpLGJuKCkpOihmbigiQ2FwdHVyaW5nIGV2ZW50IHdpdGhvdXQgYSBzdGFjayB0cmFjZSIpLHluKCkudGhlbihudWxsLCgoKT0+e2ZuKCJTZW5kaW5nIEFOUiBldmVudCBmYWlsZWQgb24gd2F0Y2hkb2cgdGltZW91dC4iKX0pKSl9KSk7bj8ub24oIm1lc3NhZ2UiLCh0PT57dC5zZXNzaW9uJiYodW49ZnQodC5zZXNzaW9uKSksdm4oKX0pKTs=';
1659
1796
 
1660
- function _optionalChain$7(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
1661
1797
  const DEFAULT_INTERVAL = 50;
1662
1798
  const DEFAULT_HANG_THRESHOLD = 5000;
1663
1799
 
@@ -2322,7 +2458,7 @@ const _koaIntegration = (() => {
2322
2458
  return;
2323
2459
  }
2324
2460
  const attributes = spanToJSON(span).data;
2325
- const route = attributes && attributes[SemanticAttributes.HTTP_ROUTE];
2461
+ const route = attributes && attributes[SEMATTRS_HTTP_ROUTE];
2326
2462
  const method = info.context.request.method.toUpperCase() || 'GET';
2327
2463
  if (route) {
2328
2464
  getIsolationScope().setTransactionName(`${method} ${route}`);
@@ -3169,9 +3305,9 @@ function setupOtel(client) {
3169
3305
  const provider = new BasicTracerProvider({
3170
3306
  sampler: new SentrySampler(client),
3171
3307
  resource: new Resource({
3172
- [SemanticResourceAttributes.SERVICE_NAME]: 'node',
3173
- [SemanticResourceAttributes.SERVICE_NAMESPACE]: 'sentry',
3174
- [SemanticResourceAttributes.SERVICE_VERSION]: SDK_VERSION,
3308
+ [SEMRESATTRS_SERVICE_NAME]: 'node',
3309
+ [SEMRESATTRS_SERVICE_NAMESPACE]: 'sentry',
3310
+ [SEMRESATTRS_SERVICE_VERSION]: SDK_VERSION,
3175
3311
  }),
3176
3312
  forceFlushTimeoutMillis: 500,
3177
3313
  });