Skip to content

Instantly share code, notes, and snippets.

@RubenVerborgh
Created July 24, 2017 18:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save RubenVerborgh/7fdcc5d7d6b182ee7c533c289632ed32 to your computer and use it in GitHub Desktop.
Save RubenVerborgh/7fdcc5d7d6b182ee7c533c289632ed32 to your computer and use it in GitHub Desktop.
<!doctype html>
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="data:text/css;base64,LyogVmVuZG9yZWQgZnJvbSBodHRwczovL2dpdGh1Yi5jb20vcm1taC93ZWJ0cmVlbWFwL2Jsb2IvOWZhMGMwNjZhMTBlYTQ0MDJkOTYwYjBjNmMxYTQzMjg0NmFjN2ZjNC93ZWJ0cmVlbWFwLmNzcyAqLwoKLndlYnRyZWVtYXAtbm9kZSB7CiAgLyogUmVxdWlyZWQgYXR0cmlidXRlcy4gKi8KICBwb3NpdGlvbjogYWJzb2x1dGU7CiAgb3ZlcmZsb3c6IGhpZGRlbjsgICAvKiBUbyBoaWRlIG92ZXJsb25nIGNhcHRpb25zLiAqLwogIGJhY2tncm91bmQ6IHdoaXRlOyAgLyogTm9kZXMgbXVzdCBiZSBvcGFxdWUgZm9yIHpJbmRleCBsYXllcmluZy4gKi8KICBib3JkZXI6IHNvbGlkIDFweCBibGFjazsgIC8qIENhbGN1bGF0aW9ucyBhc3N1bWUgMXB4IGJvcmRlci4gKi8KCiAgLyogT3B0aW9uYWw6IENTUyBhbmltYXRpb24uICovCiAgdHJhbnNpdGlvbjogdG9wICAgIDAuM3MsCiAgICAgICAgICAgICAgbGVmdCAgIDAuM3MsCiAgICAgICAgICAgICAgd2lkdGggIDAuM3MsCiAgICAgICAgICAgICAgaGVpZ2h0IDAuM3M7Cn0KCi8qIE9wdGlvbmFsOiBoaWdobGlnaHQgbm9kZXMgb24gbW91c2VvdmVyLiAqLwoud2VidHJlZW1hcC1ub2RlOmhvdmVyIHsKICBiYWNrZ3JvdW5kOiAjZWVlOwp9CgovKiBPcHRpb25hbDogRGlmZmVyZW50IGJhY2tncm91bmQgY29sb3JzIGRlcGVuZGluZyBvbiBzeW1ib2wuICovCi53ZWJ0cmVlbWFwLXN5bWJvbC1ic3MgewogIGJhY2tncm91bmQ6ICM2NkMyQTU7Cn0KLndlYnRyZWVtYXAtc3ltYm9sLWRhdGEgewogIGJhY2tncm91bmQ6ICNGQzhENjI7Cn0KLndlYnRyZWVtYXAtc3ltYm9sLXJlYWQtb25seV9kYXRhIHsKICBiYWNrZ3JvdW5kOiAjOERBMENCOwp9Ci53ZWJ0cmVlbWFwLXN5bWJvbC1jb2RlIHsKICBiYWNrZ3JvdW5kOiAjRTc4QUMzOwp9Ci53ZWJ0cmVlbWFwLXN5bWJvbC13ZWFrX3N5bWJvbCB7CiAgYmFja2dyb3VuZDogI0E2RDg1NDsKfQoud2VidHJlZW1hcC1zeW1ib2wtYnNzLndlYnRyZWVtYXAtYWdncmVnYXRlIHsKICBiYWNrZ3JvdW5kOiAjQjNFMkNEOwp9Ci53ZWJ0cmVlbWFwLXN5bWJvbC1kYXRhLndlYnRyZWVtYXAtYWdncmVnYXRlIHsKICBiYWNrZ3JvdW5kOiAjRkRDREFDOwp9Ci53ZWJ0cmVlbWFwLXN5bWJvbC1yZWFkLW9ubHlfZGF0YS53ZWJ0cmVlbWFwLWFnZ3JlZ2F0ZSB7CiAgYmFja2dyb3VuZDogI0NCRDVFODsKfQoud2VidHJlZW1hcC1zeW1ib2wtY29kZS53ZWJ0cmVlbWFwLWFnZ3JlZ2F0ZSB7CiAgYmFja2dyb3VuZDogI0Y0Q0FFNDsKfQoud2VidHJlZW1hcC1zeW1ib2wtd2Vha19zeW1ib2wud2VidHJlZW1hcC1hZ2dyZWdhdGUgewogIGJhY2tncm91bmQ6ICNFNkY1Qzk7Cn0KCiNsZWdlbmQgPiAqIHsKICBib3JkZXI6IHNvbGlkIDFweCAjNDQ0Owp9CgovKiBPcHRpb25hbDogRGlmZmVyZW50IGJvcmRlcnMgZGVwZW5kaW5nIG9uIGxldmVsLiAqLwoud2VidHJlZW1hcC1sZXZlbDAgewogIGJvcmRlcjogc29saWQgMXB4ICM0NDQ7Cn0KLndlYnRyZWVtYXAtbGV2ZWwxIHsKICBib3JkZXI6IHNvbGlkIDFweCAjNjY2Owp9Ci53ZWJ0cmVlbWFwLWxldmVsMiB7CiAgYm9yZGVyOiBzb2xpZCAxcHggIzg4ODsKfQoud2VidHJlZW1hcC1sZXZlbDMgewogIGJvcmRlcjogc29saWQgMXB4ICNhYWE7Cn0KLndlYnRyZWVtYXAtbGV2ZWw0IHsKICBib3JkZXI6IHNvbGlkIDFweCAjY2NjOwp9CgovKiBPcHRpb25hbDogc3R5bGluZyBvbiBub2RlIGNhcHRpb25zLiAqLwoud2VidHJlZW1hcC1jYXB0aW9uIHsKICBmb250LWZhbWlseTogc2Fucy1zZXJpZjsKICBmb250LXNpemU6IDExcHg7CiAgcGFkZGluZzogMnB4OwogIHRleHQtYWxpZ246IGNlbnRlcjsKfQoKLyogT3B0aW9uYWw6IHN0eWxpbmcgb24gY2FwdGlvbnMgb24gbW91c2UgaG92ZXIuICovCi8qLndlYnRyZWVtYXAtbm9kZTpob3ZlciA+IC53ZWJ0cmVlbWFwLWNhcHRpb24gewogIHRleHQtZGVjb3JhdGlvbjogdW5kZXJsaW5lOwp9Ki8K">
<title>solid-auth-client.min.js - Source Map Explorer</title>
<style>
html, body {
height: 100%;
}
body {
font-family: sans-serif;
font-size: 0.8em;
margin: 0;
}
#map {
top: 10px;
bottom: 10px;
left: 10px;
right: 10px;
position: absolute;
cursor: pointer;
-webkit-user-select: none;
}
</style>
</head>
<body>
<div id='map'></div>
</body>
<script>
// https://stackoverflow.com/a/18650828/388951
function formatBytes(bytes, decimals) {
if (bytes == 0) return '0 B';
var k = 1000,
dm = decimals || 2,
sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'],
i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
}
</script>
<script>
var tree = {
"//webpack/universalModuleDefinition": 455,
"//solid-auth-client.min.js": 13,
"webpack/bootstrap faa6bd79d58dfe98b320": 482,
"//Users/ruben/oidc-rp/~/@trust/json-document/lib/index.js": 150,
"//Users/ruben/oidc-rp/~/base64url/index.js": 54,
"//~/buffer/index.js": 19961,
"//(webpack)/buildin/global.js": 145,
"//Users/ruben/oidc-rp/~/@trust/jose/lib/schemas/JWKSchema.js": 517,
"external \"crypto\"": 13,
"//~/assert/assert.js": 4380,
"//src/storage.js": 618,
"//Users/ruben/oidc-rp/~/@trust/jose/lib/index.js": 234,
"//Users/ruben/oidc-rp/~/@trust/jose/lib/jose/JWA.js": 814,
"//Users/ruben/oidc-rp/~/@trust/json-document/lib/JSONPointer.js": 2457,
"external \"URL\"": 13,
"//~/auth-header/dist/util.js": 322,
"//Users/ruben/oidc-rp/src/FormUrlEncoded.js": 398,
"//Users/ruben/oidc-rp/src/onHttpError.js": 259,
"//src/browser-util.js": 326,
"//src/session.js": 271,
"//Users/ruben/oidc-rp/~/@trust/jose/lib/errors/DataError.js": 967,
"//Users/ruben/oidc-rp/~/@trust/jose/lib/errors/NotSupportedError.js": 1017,
"//Users/ruben/oidc-rp/~/@trust/jose/lib/errors/index.js": 54,
"//Users/ruben/oidc-rp/~/@trust/jose/lib/jose/JWK.js": 1365,
"//Users/ruben/oidc-rp/~/@trust/jose/lib/jose/JWS.js": 1451,
"//Users/ruben/oidc-rp/~/@trust/jose/lib/schemas/Base64URLSchema.js": 84,
"//Users/ruben/oidc-rp/~/@trust/jose/lib/schemas/JOSEHeaderSchema.js": 475,
"//Users/ruben/oidc-rp/~/@trust/jose/lib/schemas/JWKSetSchema.js": 113,
"//Users/ruben/oidc-rp/~/@trust/jose/lib/schemas/JWTClaimsSetSchema.js": 369,
"//Users/ruben/oidc-rp/~/@trust/jose/lib/schemas/JWTSchema.js": 594,
"//Users/ruben/oidc-rp/~/@trust/jose/lib/text-encoder/index.js": 66,
"//Users/ruben/oidc-rp/~/@trust/json-document/lib/Formats.js": 2555,
"//Users/ruben/oidc-rp/~/@trust/json-document/lib/Initializer.js": 7607,
"//Users/ruben/oidc-rp/~/@trust/json-document/lib/JSONPatch.js": 2288,
"//Users/ruben/oidc-rp/~/@trust/json-document/lib/Validator.js": 16410,
"//~/isomorphic-fetch/fetch-npm-browserify.js": 39,
"external \"fetch\"": 13,
"//src/api.js": 1183,
"//~/auth-header/dist/format.js": 1572,
"//~/auth-header/dist/index.js": 197,
"//~/auth-header/dist/parse.js": 676,
"//Users/ruben/oidc-rp/src/AuthenticationRequest.js": 1444,
"//Users/ruben/oidc-rp/src/AuthenticationResponse.js": 5733,
"//Users/ruben/oidc-rp/src/IDToken.js": 220,
"//Users/ruben/oidc-rp/src/IDTokenSchema.js": 372,
"//Users/ruben/oidc-rp/src/RelyingParty.js": 3399,
"//Users/ruben/oidc-rp/src/RelyingPartySchema.js": 616,
"//Users/ruben/oidc-rp/src/index.js": 18,
"//src/authn-fetch.js": 610,
"//src/index.js": 270,
"//src/webid-oidc.js": 1642,
"//src/webid-tls.js": 179,
"//Users/ruben/oidc-rp/~/@trust/jose/lib/algorithms/HMAC.js": 893,
"//Users/ruben/oidc-rp/~/@trust/jose/lib/algorithms/RSASSA-PKCS1-v1_5.js": 1087,
"//Users/ruben/oidc-rp/~/@trust/jose/lib/algorithms/SupportedAlgorithms.js": 724,
"//Users/ruben/oidc-rp/~/@trust/jose/lib/algorithms/index.js": 1270,
"//Users/ruben/oidc-rp/~/@trust/jose/lib/formats/index.js": 259,
"//Users/ruben/oidc-rp/~/@trust/jose/lib/jose/JWKSet.js": 1737,
"//Users/ruben/oidc-rp/~/@trust/jose/lib/jose/JWT.js": 3042,
"//Users/ruben/oidc-rp/~/@trust/json-document/lib/JSONDocument.js": 1308,
"//Users/ruben/oidc-rp/~/@trust/json-document/lib/JSONMapping.js": 769,
"//Users/ruben/oidc-rp/~/@trust/json-document/lib/JSONSchema.js": 1478,
"//Users/ruben/oidc-rp/~/base64url/dist/base64url.js": 541,
"//Users/ruben/oidc-rp/~/base64url/dist/pad-string.js": 201,
"//~/base64-js/index.js": 1338,
"//~/ieee754/index.js": 868,
"//~/isarray/index.js": 91,
"//~/process/browser.js": 1671,
"//~/util/~/inherits/inherits_browser.js": 298,
"//~/util/support/isBufferBrowser.js": 139,
"//~/util/util.js": 6051,
"//~/whatwg-fetch/fetch.js": 7237,
"external \"TextEncoder\"": 17
};
</script>
<script src="data:application/javascript;base64,Ly8gICAgIFVuZGVyc2NvcmUuanMgMS44LjMKLy8gICAgIGh0dHA6Ly91bmRlcnNjb3JlanMub3JnCi8vICAgICAoYykgMjAwOS0yMDE1IEplcmVteSBBc2hrZW5hcywgRG9jdW1lbnRDbG91ZCBhbmQgSW52ZXN0aWdhdGl2ZSBSZXBvcnRlcnMgJiBFZGl0b3JzCi8vICAgICBVbmRlcnNjb3JlIG1heSBiZSBmcmVlbHkgZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlLgoKKGZ1bmN0aW9uKCkgewoKICAvLyBCYXNlbGluZSBzZXR1cAogIC8vIC0tLS0tLS0tLS0tLS0tCgogIC8vIEVzdGFibGlzaCB0aGUgcm9vdCBvYmplY3QsIGB3aW5kb3dgIGluIHRoZSBicm93c2VyLCBvciBgZXhwb3J0c2Agb24gdGhlIHNlcnZlci4KICB2YXIgcm9vdCA9IHRoaXM7CgogIC8vIFNhdmUgdGhlIHByZXZpb3VzIHZhbHVlIG9mIHRoZSBgX2AgdmFyaWFibGUuCiAgdmFyIHByZXZpb3VzVW5kZXJzY29yZSA9IHJvb3QuXzsKCiAgLy8gU2F2ZSBieXRlcyBpbiB0aGUgbWluaWZpZWQgKGJ1dCBub3QgZ3ppcHBlZCkgdmVyc2lvbjoKICB2YXIgQXJyYXlQcm90byA9IEFycmF5LnByb3RvdHlwZSwgT2JqUHJvdG8gPSBPYmplY3QucHJvdG90eXBlLCBGdW5jUHJvdG8gPSBGdW5jdGlvbi5wcm90b3R5cGU7CgogIC8vIENyZWF0ZSBxdWljayByZWZlcmVuY2UgdmFyaWFibGVzIGZvciBzcGVlZCBhY2Nlc3MgdG8gY29yZSBwcm90b3R5cGVzLgogIHZhcgogICAgcHVzaCAgICAgICAgICAgICA9IEFycmF5UHJvdG8ucHVzaCwKICAgIHNsaWNlICAgICAgICAgICAgPSBBcnJheVByb3RvLnNsaWNlLAogICAgdG9TdHJpbmcgICAgICAgICA9IE9ialByb3RvLnRvU3RyaW5nLAogICAgaGFzT3duUHJvcGVydHkgICA9IE9ialByb3RvLmhhc093blByb3BlcnR5OwoKICAvLyBBbGwgKipFQ01BU2NyaXB0IDUqKiBuYXRpdmUgZnVuY3Rpb24gaW1wbGVtZW50YXRpb25zIHRoYXQgd2UgaG9wZSB0byB1c2UKICAvLyBhcmUgZGVjbGFyZWQgaGVyZS4KICB2YXIKICAgIG5hdGl2ZUlzQXJyYXkgICAgICA9IEFycmF5LmlzQXJyYXksCiAgICBuYXRpdmVLZXlzICAgICAgICAgPSBPYmplY3Qua2V5cywKICAgIG5hdGl2ZUJpbmQgICAgICAgICA9IEZ1bmNQcm90by5iaW5kLAogICAgbmF0aXZlQ3JlYXRlICAgICAgID0gT2JqZWN0LmNyZWF0ZTsKCiAgLy8gTmFrZWQgZnVuY3Rpb24gcmVmZXJlbmNlIGZvciBzdXJyb2dhdGUtcHJvdG90eXBlLXN3YXBwaW5nLgogIHZhciBDdG9yID0gZnVuY3Rpb24oKXt9OwoKICAvLyBDcmVhdGUgYSBzYWZlIHJlZmVyZW5jZSB0byB0aGUgVW5kZXJzY29yZSBvYmplY3QgZm9yIHVzZSBiZWxvdy4KICB2YXIgXyA9IGZ1bmN0aW9uKG9iaikgewogICAgaWYgKG9iaiBpbnN0YW5jZW9mIF8pIHJldHVybiBvYmo7CiAgICBpZiAoISh0aGlzIGluc3RhbmNlb2YgXykpIHJldHVybiBuZXcgXyhvYmopOwogICAgdGhpcy5fd3JhcHBlZCA9IG9iajsKICB9OwoKICAvLyBFeHBvcnQgdGhlIFVuZGVyc2NvcmUgb2JqZWN0IGZvciAqKk5vZGUuanMqKiwgd2l0aAogIC8vIGJhY2t3YXJkcy1jb21wYXRpYmlsaXR5IGZvciB0aGUgb2xkIGByZXF1aXJlKClgIEFQSS4gSWYgd2UncmUgaW4KICAvLyB0aGUgYnJvd3NlciwgYWRkIGBfYCBhcyBhIGdsb2JhbCBvYmplY3QuCiAgaWYgKHR5cGVvZiBleHBvcnRzICE9PSAndW5kZWZpbmVkJykgewogICAgaWYgKHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnICYmIG1vZHVsZS5leHBvcnRzKSB7CiAgICAgIGV4cG9ydHMgPSBtb2R1bGUuZXhwb3J0cyA9IF87CiAgICB9CiAgICBleHBvcnRzLl8gPSBfOwogIH0gZWxzZSB7CiAgICByb290Ll8gPSBfOwogIH0KCiAgLy8gQ3VycmVudCB2ZXJzaW9uLgogIF8uVkVSU0lPTiA9ICcxLjguMyc7CgogIC8vIEludGVybmFsIGZ1bmN0aW9uIHRoYXQgcmV0dXJucyBhbiBlZmZpY2llbnQgKGZvciBjdXJyZW50IGVuZ2luZXMpIHZlcnNpb24KICAvLyBvZiB0aGUgcGFzc2VkLWluIGNhbGxiYWNrLCB0byBiZSByZXBlYXRlZGx5IGFwcGxpZWQgaW4gb3RoZXIgVW5kZXJzY29yZQogIC8vIGZ1bmN0aW9ucy4KICB2YXIgb3B0aW1pemVDYiA9IGZ1bmN0aW9uKGZ1bmMsIGNvbnRleHQsIGFyZ0NvdW50KSB7CiAgICBpZiAoY29udGV4dCA9PT0gdm9pZCAwKSByZXR1cm4gZnVuYzsKICAgIHN3aXRjaCAoYXJnQ291bnQgPT0gbnVsbCA/IDMgOiBhcmdDb3VudCkgewogICAgICBjYXNlIDE6IHJldHVybiBmdW5jdGlvbih2YWx1ZSkgewogICAgICAgIHJldHVybiBmdW5jLmNhbGwoY29udGV4dCwgdmFsdWUpOwogICAgICB9OwogICAgICBjYXNlIDI6IHJldHVybiBmdW5jdGlvbih2YWx1ZSwgb3RoZXIpIHsKICAgICAgICByZXR1cm4gZnVuYy5jYWxsKGNvbnRleHQsIHZhbHVlLCBvdGhlcik7CiAgICAgIH07CiAgICAgIGNhc2UgMzogcmV0dXJuIGZ1bmN0aW9uKHZhbHVlLCBpbmRleCwgY29sbGVjdGlvbikgewogICAgICAgIHJldHVybiBmdW5jLmNhbGwoY29udGV4dCwgdmFsdWUsIGluZGV4LCBjb2xsZWN0aW9uKTsKICAgICAgfTsKICAgICAgY2FzZSA0OiByZXR1cm4gZnVuY3Rpb24oYWNjdW11bGF0b3IsIHZhbHVlLCBpbmRleCwgY29sbGVjdGlvbikgewogICAgICAgIHJldHVybiBmdW5jLmNhbGwoY29udGV4dCwgYWNjdW11bGF0b3IsIHZhbHVlLCBpbmRleCwgY29sbGVjdGlvbik7CiAgICAgIH07CiAgICB9CiAgICByZXR1cm4gZnVuY3Rpb24oKSB7CiAgICAgIHJldHVybiBmdW5jLmFwcGx5KGNvbnRleHQsIGFyZ3VtZW50cyk7CiAgICB9OwogIH07CgogIC8vIEEgbW9zdGx5LWludGVybmFsIGZ1bmN0aW9uIHRvIGdlbmVyYXRlIGNhbGxiYWNrcyB0aGF0IGNhbiBiZSBhcHBsaWVkCiAgLy8gdG8gZWFjaCBlbGVtZW50IGluIGEgY29sbGVjdGlvbiwgcmV0dXJuaW5nIHRoZSBkZXNpcmVkIHJlc3VsdCDigJQgZWl0aGVyCiAgLy8gaWRlbnRpdHksIGFuIGFyYml0cmFyeSBjYWxsYmFjaywgYSBwcm9wZXJ0eSBtYXRjaGVyLCBvciBhIHByb3BlcnR5IGFjY2Vzc29yLgogIHZhciBjYiA9IGZ1bmN0aW9uKHZhbHVlLCBjb250ZXh0LCBhcmdDb3VudCkgewogICAgaWYgKHZhbHVlID09IG51bGwpIHJldHVybiBfLmlkZW50aXR5OwogICAgaWYgKF8uaXNGdW5jdGlvbih2YWx1ZSkpIHJldHVybiBvcHRpbWl6ZUNiKHZhbHVlLCBjb250ZXh0LCBhcmdDb3VudCk7CiAgICBpZiAoXy5pc09iamVjdCh2YWx1ZSkpIHJldHVybiBfLm1hdGNoZXIodmFsdWUpOwogICAgcmV0dXJuIF8ucHJvcGVydHkodmFsdWUpOwogIH07CiAgXy5pdGVyYXRlZSA9IGZ1bmN0aW9uKHZhbHVlLCBjb250ZXh0KSB7CiAgICByZXR1cm4gY2IodmFsdWUsIGNvbnRleHQsIEluZmluaXR5KTsKICB9OwoKICAvLyBBbiBpbnRlcm5hbCBmdW5jdGlvbiBmb3IgY3JlYXRpbmcgYXNzaWduZXIgZnVuY3Rpb25zLgogIHZhciBjcmVhdGVBc3NpZ25lciA9IGZ1bmN0aW9uKGtleXNGdW5jLCB1bmRlZmluZWRPbmx5KSB7CiAgICByZXR1cm4gZnVuY3Rpb24ob2JqKSB7CiAgICAgIHZhciBsZW5ndGggPSBhcmd1bWVudHMubGVuZ3RoOwogICAgICBpZiAobGVuZ3RoIDwgMiB8fCBvYmogPT0gbnVsbCkgcmV0dXJuIG9iajsKICAgICAgZm9yICh2YXIgaW5kZXggPSAxOyBpbmRleCA8IGxlbmd0aDsgaW5kZXgrKykgewogICAgICAgIHZhciBzb3VyY2UgPSBhcmd1bWVudHNbaW5kZXhdLAogICAgICAgICAgICBrZXlzID0ga2V5c0Z1bmMoc291cmNlKSwKICAgICAgICAgICAgbCA9IGtleXMubGVuZ3RoOwogICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbDsgaSsrKSB7CiAgICAgICAgICB2YXIga2V5ID0ga2V5c1tpXTsKICAgICAgICAgIGlmICghdW5kZWZpbmVkT25seSB8fCBvYmpba2V5XSA9PT0gdm9pZCAwKSBvYmpba2V5XSA9IHNvdXJjZVtrZXldOwogICAgICAgIH0KICAgICAgfQogICAgICByZXR1cm4gb2JqOwogICAgfTsKICB9OwoKICAvLyBBbiBpbnRlcm5hbCBmdW5jdGlvbiBmb3IgY3JlYXRpbmcgYSBuZXcgb2JqZWN0IHRoYXQgaW5oZXJpdHMgZnJvbSBhbm90aGVyLgogIHZhciBiYXNlQ3JlYXRlID0gZnVuY3Rpb24ocHJvdG90eXBlKSB7CiAgICBpZiAoIV8uaXNPYmplY3QocHJvdG90eXBlKSkgcmV0dXJuIHt9OwogICAgaWYgKG5hdGl2ZUNyZWF0ZSkgcmV0dXJuIG5hdGl2ZUNyZWF0ZShwcm90b3R5cGUpOwogICAgQ3Rvci5wcm90b3R5cGUgPSBwcm90b3R5cGU7CiAgICB2YXIgcmVzdWx0ID0gbmV3IEN0b3I7CiAgICBDdG9yLnByb3RvdHlwZSA9IG51bGw7CiAgICByZXR1cm4gcmVzdWx0OwogIH07CgogIHZhciBwcm9wZXJ0eSA9IGZ1bmN0aW9uKGtleSkgewogICAgcmV0dXJuIGZ1bmN0aW9uKG9iaikgewogICAgICByZXR1cm4gb2JqID09IG51bGwgPyB2b2lkIDAgOiBvYmpba2V5XTsKICAgIH07CiAgfTsKCiAgLy8gSGVscGVyIGZvciBjb2xsZWN0aW9uIG1ldGhvZHMgdG8gZGV0ZXJtaW5lIHdoZXRoZXIgYSBjb2xsZWN0aW9uCiAgLy8gc2hvdWxkIGJlIGl0ZXJhdGVkIGFzIGFuIGFycmF5IG9yIGFzIGFuIG9iamVjdAogIC8vIFJlbGF0ZWQ6IGh0dHA6Ly9wZW9wbGUubW96aWxsYS5vcmcvfmpvcmVuZG9yZmYvZXM2LWRyYWZ0Lmh0bWwjc2VjLXRvbGVuZ3RoCiAgLy8gQXZvaWRzIGEgdmVyeSBuYXN0eSBpT1MgOCBKSVQgYnVnIG9uIEFSTS02NC4gIzIwOTQKICB2YXIgTUFYX0FSUkFZX0lOREVYID0gTWF0aC5wb3coMiwgNTMpIC0gMTsKICB2YXIgZ2V0TGVuZ3RoID0gcHJvcGVydHkoJ2xlbmd0aCcpOwogIHZhciBpc0FycmF5TGlrZSA9IGZ1bmN0aW9uKGNvbGxlY3Rpb24pIHsKICAgIHZhciBsZW5ndGggPSBnZXRMZW5ndGgoY29sbGVjdGlvbik7CiAgICByZXR1cm4gdHlwZW9mIGxlbmd0aCA9PSAnbnVtYmVyJyAmJiBsZW5ndGggPj0gMCAmJiBsZW5ndGggPD0gTUFYX0FSUkFZX0lOREVYOwogIH07CgogIC8vIENvbGxlY3Rpb24gRnVuY3Rpb25zCiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0KCiAgLy8gVGhlIGNvcm5lcnN0b25lLCBhbiBgZWFjaGAgaW1wbGVtZW50YXRpb24sIGFrYSBgZm9yRWFjaGAuCiAgLy8gSGFuZGxlcyByYXcgb2JqZWN0cyBpbiBhZGRpdGlvbiB0byBhcnJheS1saWtlcy4gVHJlYXRzIGFsbAogIC8vIHNwYXJzZSBhcnJheS1saWtlcyBhcyBpZiB0aGV5IHdlcmUgZGVuc2UuCiAgXy5lYWNoID0gXy5mb3JFYWNoID0gZnVuY3Rpb24ob2JqLCBpdGVyYXRlZSwgY29udGV4dCkgewogICAgaXRlcmF0ZWUgPSBvcHRpbWl6ZUNiKGl0ZXJhdGVlLCBjb250ZXh0KTsKICAgIHZhciBpLCBsZW5ndGg7CiAgICBpZiAoaXNBcnJheUxpa2Uob2JqKSkgewogICAgICBmb3IgKGkgPSAwLCBsZW5ndGggPSBvYmoubGVuZ3RoOyBpIDwgbGVuZ3RoOyBpKyspIHsKICAgICAgICBpdGVyYXRlZShvYmpbaV0sIGksIG9iaik7CiAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgIHZhciBrZXlzID0gXy5rZXlzKG9iaik7CiAgICAgIGZvciAoaSA9IDAsIGxlbmd0aCA9IGtleXMubGVuZ3RoOyBpIDwgbGVuZ3RoOyBpKyspIHsKICAgICAgICBpdGVyYXRlZShvYmpba2V5c1tpXV0sIGtleXNbaV0sIG9iaik7CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBvYmo7CiAgfTsKCiAgLy8gUmV0dXJuIHRoZSByZXN1bHRzIG9mIGFwcGx5aW5nIHRoZSBpdGVyYXRlZSB0byBlYWNoIGVsZW1lbnQuCiAgXy5tYXAgPSBfLmNvbGxlY3QgPSBmdW5jdGlvbihvYmosIGl0ZXJhdGVlLCBjb250ZXh0KSB7CiAgICBpdGVyYXRlZSA9IGNiKGl0ZXJhdGVlLCBjb250ZXh0KTsKICAgIHZhciBrZXlzID0gIWlzQXJyYXlMaWtlKG9iaikgJiYgXy5rZXlzKG9iaiksCiAgICAgICAgbGVuZ3RoID0gKGtleXMgfHwgb2JqKS5sZW5ndGgsCiAgICAgICAgcmVzdWx0cyA9IEFycmF5KGxlbmd0aCk7CiAgICBmb3IgKHZhciBpbmRleCA9IDA7IGluZGV4IDwgbGVuZ3RoOyBpbmRleCsrKSB7CiAgICAgIHZhciBjdXJyZW50S2V5ID0ga2V5cyA/IGtleXNbaW5kZXhdIDogaW5kZXg7CiAgICAgIHJlc3VsdHNbaW5kZXhdID0gaXRlcmF0ZWUob2JqW2N1cnJlbnRLZXldLCBjdXJyZW50S2V5LCBvYmopOwogICAgfQogICAgcmV0dXJuIHJlc3VsdHM7CiAgfTsKCiAgLy8gQ3JlYXRlIGEgcmVkdWNpbmcgZnVuY3Rpb24gaXRlcmF0aW5nIGxlZnQgb3IgcmlnaHQuCiAgZnVuY3Rpb24gY3JlYXRlUmVkdWNlKGRpcikgewogICAgLy8gT3B0aW1pemVkIGl0ZXJhdG9yIGZ1bmN0aW9uIGFzIHVzaW5nIGFyZ3VtZW50cy5sZW5ndGgKICAgIC8vIGluIHRoZSBtYWluIGZ1bmN0aW9uIHdpbGwgZGVvcHRpbWl6ZSB0aGUsIHNlZSAjMTk5MS4KICAgIGZ1bmN0aW9uIGl0ZXJhdG9yKG9iaiwgaXRlcmF0ZWUsIG1lbW8sIGtleXMsIGluZGV4LCBsZW5ndGgpIHsKICAgICAgZm9yICg7IGluZGV4ID49IDAgJiYgaW5kZXggPCBsZW5ndGg7IGluZGV4ICs9IGRpcikgewogICAgICAgIHZhciBjdXJyZW50S2V5ID0ga2V5cyA/IGtleXNbaW5kZXhdIDogaW5kZXg7CiAgICAgICAgbWVtbyA9IGl0ZXJhdGVlKG1lbW8sIG9ialtjdXJyZW50S2V5XSwgY3VycmVudEtleSwgb2JqKTsKICAgICAgfQogICAgICByZXR1cm4gbWVtbzsKICAgIH0KCiAgICByZXR1cm4gZnVuY3Rpb24ob2JqLCBpdGVyYXRlZSwgbWVtbywgY29udGV4dCkgewogICAgICBpdGVyYXRlZSA9IG9wdGltaXplQ2IoaXRlcmF0ZWUsIGNvbnRleHQsIDQpOwogICAgICB2YXIga2V5cyA9ICFpc0FycmF5TGlrZShvYmopICYmIF8ua2V5cyhvYmopLAogICAgICAgICAgbGVuZ3RoID0gKGtleXMgfHwgb2JqKS5sZW5ndGgsCiAgICAgICAgICBpbmRleCA9IGRpciA+IDAgPyAwIDogbGVuZ3RoIC0gMTsKICAgICAgLy8gRGV0ZXJtaW5lIHRoZSBpbml0aWFsIHZhbHVlIGlmIG5vbmUgaXMgcHJvdmlkZWQuCiAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoIDwgMykgewogICAgICAgIG1lbW8gPSBvYmpba2V5cyA/IGtleXNbaW5kZXhdIDogaW5kZXhdOwogICAgICAgIGluZGV4ICs9IGRpcjsKICAgICAgfQogICAgICByZXR1cm4gaXRlcmF0b3Iob2JqLCBpdGVyYXRlZSwgbWVtbywga2V5cywgaW5kZXgsIGxlbmd0aCk7CiAgICB9OwogIH0KCiAgLy8gKipSZWR1Y2UqKiBidWlsZHMgdXAgYSBzaW5nbGUgcmVzdWx0IGZyb20gYSBsaXN0IG9mIHZhbHVlcywgYWthIGBpbmplY3RgLAogIC8vIG9yIGBmb2xkbGAuCiAgXy5yZWR1Y2UgPSBfLmZvbGRsID0gXy5pbmplY3QgPSBjcmVhdGVSZWR1Y2UoMSk7CgogIC8vIFRoZSByaWdodC1hc3NvY2lhdGl2ZSB2ZXJzaW9uIG9mIHJlZHVjZSwgYWxzbyBrbm93biBhcyBgZm9sZHJgLgogIF8ucmVkdWNlUmlnaHQgPSBfLmZvbGRyID0gY3JlYXRlUmVkdWNlKC0xKTsKCiAgLy8gUmV0dXJuIHRoZSBmaXJzdCB2YWx1ZSB3aGljaCBwYXNzZXMgYSB0cnV0aCB0ZXN0LiBBbGlhc2VkIGFzIGBkZXRlY3RgLgogIF8uZmluZCA9IF8uZGV0ZWN0ID0gZnVuY3Rpb24ob2JqLCBwcmVkaWNhdGUsIGNvbnRleHQpIHsKICAgIHZhciBrZXk7CiAgICBpZiAoaXNBcnJheUxpa2Uob2JqKSkgewogICAgICBrZXkgPSBfLmZpbmRJbmRleChvYmosIHByZWRpY2F0ZSwgY29udGV4dCk7CiAgICB9IGVsc2UgewogICAgICBrZXkgPSBfLmZpbmRLZXkob2JqLCBwcmVkaWNhdGUsIGNvbnRleHQpOwogICAgfQogICAgaWYgKGtleSAhPT0gdm9pZCAwICYmIGtleSAhPT0gLTEpIHJldHVybiBvYmpba2V5XTsKICB9OwoKICAvLyBSZXR1cm4gYWxsIHRoZSBlbGVtZW50cyB0aGF0IHBhc3MgYSB0cnV0aCB0ZXN0LgogIC8vIEFsaWFzZWQgYXMgYHNlbGVjdGAuCiAgXy5maWx0ZXIgPSBfLnNlbGVjdCA9IGZ1bmN0aW9uKG9iaiwgcHJlZGljYXRlLCBjb250ZXh0KSB7CiAgICB2YXIgcmVzdWx0cyA9IFtdOwogICAgcHJlZGljYXRlID0gY2IocHJlZGljYXRlLCBjb250ZXh0KTsKICAgIF8uZWFjaChvYmosIGZ1bmN0aW9uKHZhbHVlLCBpbmRleCwgbGlzdCkgewogICAgICBpZiAocHJlZGljYXRlKHZhbHVlLCBpbmRleCwgbGlzdCkpIHJlc3VsdHMucHVzaCh2YWx1ZSk7CiAgICB9KTsKICAgIHJldHVybiByZXN1bHRzOwogIH07CgogIC8vIFJldHVybiBhbGwgdGhlIGVsZW1lbnRzIGZvciB3aGljaCBhIHRydXRoIHRlc3QgZmFpbHMuCiAgXy5yZWplY3QgPSBmdW5jdGlvbihvYmosIHByZWRpY2F0ZSwgY29udGV4dCkgewogICAgcmV0dXJuIF8uZmlsdGVyKG9iaiwgXy5uZWdhdGUoY2IocHJlZGljYXRlKSksIGNvbnRleHQpOwogIH07CgogIC8vIERldGVybWluZSB3aGV0aGVyIGFsbCBvZiB0aGUgZWxlbWVudHMgbWF0Y2ggYSB0cnV0aCB0ZXN0LgogIC8vIEFsaWFzZWQgYXMgYGFsbGAuCiAgXy5ldmVyeSA9IF8uYWxsID0gZnVuY3Rpb24ob2JqLCBwcmVkaWNhdGUsIGNvbnRleHQpIHsKICAgIHByZWRpY2F0ZSA9IGNiKHByZWRpY2F0ZSwgY29udGV4dCk7CiAgICB2YXIga2V5cyA9ICFpc0FycmF5TGlrZShvYmopICYmIF8ua2V5cyhvYmopLAogICAgICAgIGxlbmd0aCA9IChrZXlzIHx8IG9iaikubGVuZ3RoOwogICAgZm9yICh2YXIgaW5kZXggPSAwOyBpbmRleCA8IGxlbmd0aDsgaW5kZXgrKykgewogICAgICB2YXIgY3VycmVudEtleSA9IGtleXMgPyBrZXlzW2luZGV4XSA6IGluZGV4OwogICAgICBpZiAoIXByZWRpY2F0ZShvYmpbY3VycmVudEtleV0sIGN1cnJlbnRLZXksIG9iaikpIHJldHVybiBmYWxzZTsKICAgIH0KICAgIHJldHVybiB0cnVlOwogIH07CgogIC8vIERldGVybWluZSBpZiBhdCBsZWFzdCBvbmUgZWxlbWVudCBpbiB0aGUgb2JqZWN0IG1hdGNoZXMgYSB0cnV0aCB0ZXN0LgogIC8vIEFsaWFzZWQgYXMgYGFueWAuCiAgXy5zb21lID0gXy5hbnkgPSBmdW5jdGlvbihvYmosIHByZWRpY2F0ZSwgY29udGV4dCkgewogICAgcHJlZGljYXRlID0gY2IocHJlZGljYXRlLCBjb250ZXh0KTsKICAgIHZhciBrZXlzID0gIWlzQXJyYXlMaWtlKG9iaikgJiYgXy5rZXlzKG9iaiksCiAgICAgICAgbGVuZ3RoID0gKGtleXMgfHwgb2JqKS5sZW5ndGg7CiAgICBmb3IgKHZhciBpbmRleCA9IDA7IGluZGV4IDwgbGVuZ3RoOyBpbmRleCsrKSB7CiAgICAgIHZhciBjdXJyZW50S2V5ID0ga2V5cyA/IGtleXNbaW5kZXhdIDogaW5kZXg7CiAgICAgIGlmIChwcmVkaWNhdGUob2JqW2N1cnJlbnRLZXldLCBjdXJyZW50S2V5LCBvYmopKSByZXR1cm4gdHJ1ZTsKICAgIH0KICAgIHJldHVybiBmYWxzZTsKICB9OwoKICAvLyBEZXRlcm1pbmUgaWYgdGhlIGFycmF5IG9yIG9iamVjdCBjb250YWlucyBhIGdpdmVuIGl0ZW0gKHVzaW5nIGA9PT1gKS4KICAvLyBBbGlhc2VkIGFzIGBpbmNsdWRlc2AgYW5kIGBpbmNsdWRlYC4KICBfLmNvbnRhaW5zID0gXy5pbmNsdWRlcyA9IF8uaW5jbHVkZSA9IGZ1bmN0aW9uKG9iaiwgaXRlbSwgZnJvbUluZGV4LCBndWFyZCkgewogICAgaWYgKCFpc0FycmF5TGlrZShvYmopKSBvYmogPSBfLnZhbHVlcyhvYmopOwogICAgaWYgKHR5cGVvZiBmcm9tSW5kZXggIT0gJ251bWJlcicgfHwgZ3VhcmQpIGZyb21JbmRleCA9IDA7CiAgICByZXR1cm4gXy5pbmRleE9mKG9iaiwgaXRlbSwgZnJvbUluZGV4KSA+PSAwOwogIH07CgogIC8vIEludm9rZSBhIG1ldGhvZCAod2l0aCBhcmd1bWVudHMpIG9uIGV2ZXJ5IGl0ZW0gaW4gYSBjb2xsZWN0aW9uLgogIF8uaW52b2tlID0gZnVuY3Rpb24ob2JqLCBtZXRob2QpIHsKICAgIHZhciBhcmdzID0gc2xpY2UuY2FsbChhcmd1bWVudHMsIDIpOwogICAgdmFyIGlzRnVuYyA9IF8uaXNGdW5jdGlvbihtZXRob2QpOwogICAgcmV0dXJuIF8ubWFwKG9iaiwgZnVuY3Rpb24odmFsdWUpIHsKICAgICAgdmFyIGZ1bmMgPSBpc0Z1bmMgPyBtZXRob2QgOiB2YWx1ZVttZXRob2RdOwogICAgICByZXR1cm4gZnVuYyA9PSBudWxsID8gZnVuYyA6IGZ1bmMuYXBwbHkodmFsdWUsIGFyZ3MpOwogICAgfSk7CiAgfTsKCiAgLy8gQ29udmVuaWVuY2UgdmVyc2lvbiBvZiBhIGNvbW1vbiB1c2UgY2FzZSBvZiBgbWFwYDogZmV0Y2hpbmcgYSBwcm9wZXJ0eS4KICBfLnBsdWNrID0gZnVuY3Rpb24ob2JqLCBrZXkpIHsKICAgIHJldHVybiBfLm1hcChvYmosIF8ucHJvcGVydHkoa2V5KSk7CiAgfTsKCiAgLy8gQ29udmVuaWVuY2UgdmVyc2lvbiBvZiBhIGNvbW1vbiB1c2UgY2FzZSBvZiBgZmlsdGVyYDogc2VsZWN0aW5nIG9ubHkgb2JqZWN0cwogIC8vIGNvbnRhaW5pbmcgc3BlY2lmaWMgYGtleTp2YWx1ZWAgcGFpcnMuCiAgXy53aGVyZSA9IGZ1bmN0aW9uKG9iaiwgYXR0cnMpIHsKICAgIHJldHVybiBfLmZpbHRlcihvYmosIF8ubWF0Y2hlcihhdHRycykpOwogIH07CgogIC8vIENvbnZlbmllbmNlIHZlcnNpb24gb2YgYSBjb21tb24gdXNlIGNhc2Ugb2YgYGZpbmRgOiBnZXR0aW5nIHRoZSBmaXJzdCBvYmplY3QKICAvLyBjb250YWluaW5nIHNwZWNpZmljIGBrZXk6dmFsdWVgIHBhaXJzLgogIF8uZmluZFdoZXJlID0gZnVuY3Rpb24ob2JqLCBhdHRycykgewogICAgcmV0dXJuIF8uZmluZChvYmosIF8ubWF0Y2hlcihhdHRycykpOwogIH07CgogIC8vIFJldHVybiB0aGUgbWF4aW11bSBlbGVtZW50IChvciBlbGVtZW50LWJhc2VkIGNvbXB1dGF0aW9uKS4KICBfLm1heCA9IGZ1bmN0aW9uKG9iaiwgaXRlcmF0ZWUsIGNvbnRleHQpIHsKICAgIHZhciByZXN1bHQgPSAtSW5maW5pdHksIGxhc3RDb21wdXRlZCA9IC1JbmZpbml0eSwKICAgICAgICB2YWx1ZSwgY29tcHV0ZWQ7CiAgICBpZiAoaXRlcmF0ZWUgPT0gbnVsbCAmJiBvYmogIT0gbnVsbCkgewogICAgICBvYmogPSBpc0FycmF5TGlrZShvYmopID8gb2JqIDogXy52YWx1ZXMob2JqKTsKICAgICAgZm9yICh2YXIgaSA9IDAsIGxlbmd0aCA9IG9iai5sZW5ndGg7IGkgPCBsZW5ndGg7IGkrKykgewogICAgICAgIHZhbHVlID0gb2JqW2ldOwogICAgICAgIGlmICh2YWx1ZSA+IHJlc3VsdCkgewogICAgICAgICAgcmVzdWx0ID0gdmFsdWU7CiAgICAgICAgfQogICAgICB9CiAgICB9IGVsc2UgewogICAgICBpdGVyYXRlZSA9IGNiKGl0ZXJhdGVlLCBjb250ZXh0KTsKICAgICAgXy5lYWNoKG9iaiwgZnVuY3Rpb24odmFsdWUsIGluZGV4LCBsaXN0KSB7CiAgICAgICAgY29tcHV0ZWQgPSBpdGVyYXRlZSh2YWx1ZSwgaW5kZXgsIGxpc3QpOwogICAgICAgIGlmIChjb21wdXRlZCA+IGxhc3RDb21wdXRlZCB8fCBjb21wdXRlZCA9PT0gLUluZmluaXR5ICYmIHJlc3VsdCA9PT0gLUluZmluaXR5KSB7CiAgICAgICAgICByZXN1bHQgPSB2YWx1ZTsKICAgICAgICAgIGxhc3RDb21wdXRlZCA9IGNvbXB1dGVkOwogICAgICAgIH0KICAgICAgfSk7CiAgICB9CiAgICByZXR1cm4gcmVzdWx0OwogIH07CgogIC8vIFJldHVybiB0aGUgbWluaW11bSBlbGVtZW50IChvciBlbGVtZW50LWJhc2VkIGNvbXB1dGF0aW9uKS4KICBfLm1pbiA9IGZ1bmN0aW9uKG9iaiwgaXRlcmF0ZWUsIGNvbnRleHQpIHsKICAgIHZhciByZXN1bHQgPSBJbmZpbml0eSwgbGFzdENvbXB1dGVkID0gSW5maW5pdHksCiAgICAgICAgdmFsdWUsIGNvbXB1dGVkOwogICAgaWYgKGl0ZXJhdGVlID09IG51bGwgJiYgb2JqICE9IG51bGwpIHsKICAgICAgb2JqID0gaXNBcnJheUxpa2Uob2JqKSA/IG9iaiA6IF8udmFsdWVzKG9iaik7CiAgICAgIGZvciAodmFyIGkgPSAwLCBsZW5ndGggPSBvYmoubGVuZ3RoOyBpIDwgbGVuZ3RoOyBpKyspIHsKICAgICAgICB2YWx1ZSA9IG9ialtpXTsKICAgICAgICBpZiAodmFsdWUgPCByZXN1bHQpIHsKICAgICAgICAgIHJlc3VsdCA9IHZhbHVlOwogICAgICAgIH0KICAgICAgfQogICAgfSBlbHNlIHsKICAgICAgaXRlcmF0ZWUgPSBjYihpdGVyYXRlZSwgY29udGV4dCk7CiAgICAgIF8uZWFjaChvYmosIGZ1bmN0aW9uKHZhbHVlLCBpbmRleCwgbGlzdCkgewogICAgICAgIGNvbXB1dGVkID0gaXRlcmF0ZWUodmFsdWUsIGluZGV4LCBsaXN0KTsKICAgICAgICBpZiAoY29tcHV0ZWQgPCBsYXN0Q29tcHV0ZWQgfHwgY29tcHV0ZWQgPT09IEluZmluaXR5ICYmIHJlc3VsdCA9PT0gSW5maW5pdHkpIHsKICAgICAgICAgIHJlc3VsdCA9IHZhbHVlOwogICAgICAgICAgbGFzdENvbXB1dGVkID0gY29tcHV0ZWQ7CiAgICAgICAgfQogICAgICB9KTsKICAgIH0KICAgIHJldHVybiByZXN1bHQ7CiAgfTsKCiAgLy8gU2h1ZmZsZSBhIGNvbGxlY3Rpb24sIHVzaW5nIHRoZSBtb2Rlcm4gdmVyc2lvbiBvZiB0aGUKICAvLyBbRmlzaGVyLVlhdGVzIHNodWZmbGVdKGh0dHA6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvRmlzaGVy4oCTWWF0ZXNfc2h1ZmZsZSkuCiAgXy5zaHVmZmxlID0gZnVuY3Rpb24ob2JqKSB7CiAgICB2YXIgc2V0ID0gaXNBcnJheUxpa2Uob2JqKSA/IG9iaiA6IF8udmFsdWVzKG9iaik7CiAgICB2YXIgbGVuZ3RoID0gc2V0Lmxlbmd0aDsKICAgIHZhciBzaHVmZmxlZCA9IEFycmF5KGxlbmd0aCk7CiAgICBmb3IgKHZhciBpbmRleCA9IDAsIHJhbmQ7IGluZGV4IDwgbGVuZ3RoOyBpbmRleCsrKSB7CiAgICAgIHJhbmQgPSBfLnJhbmRvbSgwLCBpbmRleCk7CiAgICAgIGlmIChyYW5kICE9PSBpbmRleCkgc2h1ZmZsZWRbaW5kZXhdID0gc2h1ZmZsZWRbcmFuZF07CiAgICAgIHNodWZmbGVkW3JhbmRdID0gc2V0W2luZGV4XTsKICAgIH0KICAgIHJldHVybiBzaHVmZmxlZDsKICB9OwoKICAvLyBTYW1wbGUgKipuKiogcmFuZG9tIHZhbHVlcyBmcm9tIGEgY29sbGVjdGlvbi4KICAvLyBJZiAqKm4qKiBpcyBub3Qgc3BlY2lmaWVkLCByZXR1cm5zIGEgc2luZ2xlIHJhbmRvbSBlbGVtZW50LgogIC8vIFRoZSBpbnRlcm5hbCBgZ3VhcmRgIGFyZ3VtZW50IGFsbG93cyBpdCB0byB3b3JrIHdpdGggYG1hcGAuCiAgXy5zYW1wbGUgPSBmdW5jdGlvbihvYmosIG4sIGd1YXJkKSB7CiAgICBpZiAobiA9PSBudWxsIHx8IGd1YXJkKSB7CiAgICAgIGlmICghaXNBcnJheUxpa2Uob2JqKSkgb2JqID0gXy52YWx1ZXMob2JqKTsKICAgICAgcmV0dXJuIG9ialtfLnJhbmRvbShvYmoubGVuZ3RoIC0gMSldOwogICAgfQogICAgcmV0dXJuIF8uc2h1ZmZsZShvYmopLnNsaWNlKDAsIE1hdGgubWF4KDAsIG4pKTsKICB9OwoKICAvLyBTb3J0IHRoZSBvYmplY3QncyB2YWx1ZXMgYnkgYSBjcml0ZXJpb24gcHJvZHVjZWQgYnkgYW4gaXRlcmF0ZWUuCiAgXy5zb3J0QnkgPSBmdW5jdGlvbihvYmosIGl0ZXJhdGVlLCBjb250ZXh0KSB7CiAgICBpdGVyYXRlZSA9IGNiKGl0ZXJhdGVlLCBjb250ZXh0KTsKICAgIHJldHVybiBfLnBsdWNrKF8ubWFwKG9iaiwgZnVuY3Rpb24odmFsdWUsIGluZGV4LCBsaXN0KSB7CiAgICAgIHJldHVybiB7CiAgICAgICAgdmFsdWU6IHZhbHVlLAogICAgICAgIGluZGV4OiBpbmRleCwKICAgICAgICBjcml0ZXJpYTogaXRlcmF0ZWUodmFsdWUsIGluZGV4LCBsaXN0KQogICAgICB9OwogICAgfSkuc29ydChmdW5jdGlvbihsZWZ0LCByaWdodCkgewogICAgICB2YXIgYSA9IGxlZnQuY3JpdGVyaWE7CiAgICAgIHZhciBiID0gcmlnaHQuY3JpdGVyaWE7CiAgICAgIGlmIChhICE9PSBiKSB7CiAgICAgICAgaWYgKGEgPiBiIHx8IGEgPT09IHZvaWQgMCkgcmV0dXJuIDE7CiAgICAgICAgaWYgKGEgPCBiIHx8IGIgPT09IHZvaWQgMCkgcmV0dXJuIC0xOwogICAgICB9CiAgICAgIHJldHVybiBsZWZ0LmluZGV4IC0gcmlnaHQuaW5kZXg7CiAgICB9KSwgJ3ZhbHVlJyk7CiAgfTsKCiAgLy8gQW4gaW50ZXJuYWwgZnVuY3Rpb24gdXNlZCBmb3IgYWdncmVnYXRlICJncm91cCBieSIgb3BlcmF0aW9ucy4KICB2YXIgZ3JvdXAgPSBmdW5jdGlvbihiZWhhdmlvcikgewogICAgcmV0dXJuIGZ1bmN0aW9uKG9iaiwgaXRlcmF0ZWUsIGNvbnRleHQpIHsKICAgICAgdmFyIHJlc3VsdCA9IHt9OwogICAgICBpdGVyYXRlZSA9IGNiKGl0ZXJhdGVlLCBjb250ZXh0KTsKICAgICAgXy5lYWNoKG9iaiwgZnVuY3Rpb24odmFsdWUsIGluZGV4KSB7CiAgICAgICAgdmFyIGtleSA9IGl0ZXJhdGVlKHZhbHVlLCBpbmRleCwgb2JqKTsKICAgICAgICBiZWhhdmlvcihyZXN1bHQsIHZhbHVlLCBrZXkpOwogICAgICB9KTsKICAgICAgcmV0dXJuIHJlc3VsdDsKICAgIH07CiAgfTsKCiAgLy8gR3JvdXBzIHRoZSBvYmplY3QncyB2YWx1ZXMgYnkgYSBjcml0ZXJpb24uIFBhc3MgZWl0aGVyIGEgc3RyaW5nIGF0dHJpYnV0ZQogIC8vIHRvIGdyb3VwIGJ5LCBvciBhIGZ1bmN0aW9uIHRoYXQgcmV0dXJucyB0aGUgY3JpdGVyaW9uLgogIF8uZ3JvdXBCeSA9IGdyb3VwKGZ1bmN0aW9uKHJlc3VsdCwgdmFsdWUsIGtleSkgewogICAgaWYgKF8uaGFzKHJlc3VsdCwga2V5KSkgcmVzdWx0W2tleV0ucHVzaCh2YWx1ZSk7IGVsc2UgcmVzdWx0W2tleV0gPSBbdmFsdWVdOwogIH0pOwoKICAvLyBJbmRleGVzIHRoZSBvYmplY3QncyB2YWx1ZXMgYnkgYSBjcml0ZXJpb24sIHNpbWlsYXIgdG8gYGdyb3VwQnlgLCBidXQgZm9yCiAgLy8gd2hlbiB5b3Uga25vdyB0aGF0IHlvdXIgaW5kZXggdmFsdWVzIHdpbGwgYmUgdW5pcXVlLgogIF8uaW5kZXhCeSA9IGdyb3VwKGZ1bmN0aW9uKHJlc3VsdCwgdmFsdWUsIGtleSkgewogICAgcmVzdWx0W2tleV0gPSB2YWx1ZTsKICB9KTsKCiAgLy8gQ291bnRzIGluc3RhbmNlcyBvZiBhbiBvYmplY3QgdGhhdCBncm91cCBieSBhIGNlcnRhaW4gY3JpdGVyaW9uLiBQYXNzCiAgLy8gZWl0aGVyIGEgc3RyaW5nIGF0dHJpYnV0ZSB0byBjb3VudCBieSwgb3IgYSBmdW5jdGlvbiB0aGF0IHJldHVybnMgdGhlCiAgLy8gY3JpdGVyaW9uLgogIF8uY291bnRCeSA9IGdyb3VwKGZ1bmN0aW9uKHJlc3VsdCwgdmFsdWUsIGtleSkgewogICAgaWYgKF8uaGFzKHJlc3VsdCwga2V5KSkgcmVzdWx0W2tleV0rKzsgZWxzZSByZXN1bHRba2V5XSA9IDE7CiAgfSk7CgogIC8vIFNhZmVseSBjcmVhdGUgYSByZWFsLCBsaXZlIGFycmF5IGZyb20gYW55dGhpbmcgaXRlcmFibGUuCiAgXy50b0FycmF5ID0gZnVuY3Rpb24ob2JqKSB7CiAgICBpZiAoIW9iaikgcmV0dXJuIFtdOwogICAgaWYgKF8uaXNBcnJheShvYmopKSByZXR1cm4gc2xpY2UuY2FsbChvYmopOwogICAgaWYgKGlzQXJyYXlMaWtlKG9iaikpIHJldHVybiBfLm1hcChvYmosIF8uaWRlbnRpdHkpOwogICAgcmV0dXJuIF8udmFsdWVzKG9iaik7CiAgfTsKCiAgLy8gUmV0dXJuIHRoZSBudW1iZXIgb2YgZWxlbWVudHMgaW4gYW4gb2JqZWN0LgogIF8uc2l6ZSA9IGZ1bmN0aW9uKG9iaikgewogICAgaWYgKG9iaiA9PSBudWxsKSByZXR1cm4gMDsKICAgIHJldHVybiBpc0FycmF5TGlrZShvYmopID8gb2JqLmxlbmd0aCA6IF8ua2V5cyhvYmopLmxlbmd0aDsKICB9OwoKICAvLyBTcGxpdCBhIGNvbGxlY3Rpb24gaW50byB0d28gYXJyYXlzOiBvbmUgd2hvc2UgZWxlbWVudHMgYWxsIHNhdGlzZnkgdGhlIGdpdmVuCiAgLy8gcHJlZGljYXRlLCBhbmQgb25lIHdob3NlIGVsZW1lbnRzIGFsbCBkbyBub3Qgc2F0aXNmeSB0aGUgcHJlZGljYXRlLgogIF8ucGFydGl0aW9uID0gZnVuY3Rpb24ob2JqLCBwcmVkaWNhdGUsIGNvbnRleHQpIHsKICAgIHByZWRpY2F0ZSA9IGNiKHByZWRpY2F0ZSwgY29udGV4dCk7CiAgICB2YXIgcGFzcyA9IFtdLCBmYWlsID0gW107CiAgICBfLmVhY2gob2JqLCBmdW5jdGlvbih2YWx1ZSwga2V5LCBvYmopIHsKICAgICAgKHByZWRpY2F0ZSh2YWx1ZSwga2V5LCBvYmopID8gcGFzcyA6IGZhaWwpLnB1c2godmFsdWUpOwogICAgfSk7CiAgICByZXR1cm4gW3Bhc3MsIGZhaWxdOwogIH07CgogIC8vIEFycmF5IEZ1bmN0aW9ucwogIC8vIC0tLS0tLS0tLS0tLS0tLQoKICAvLyBHZXQgdGhlIGZpcnN0IGVsZW1lbnQgb2YgYW4gYXJyYXkuIFBhc3NpbmcgKipuKiogd2lsbCByZXR1cm4gdGhlIGZpcnN0IE4KICAvLyB2YWx1ZXMgaW4gdGhlIGFycmF5LiBBbGlhc2VkIGFzIGBoZWFkYCBhbmQgYHRha2VgLiBUaGUgKipndWFyZCoqIGNoZWNrCiAgLy8gYWxsb3dzIGl0IHRvIHdvcmsgd2l0aCBgXy5tYXBgLgogIF8uZmlyc3QgPSBfLmhlYWQgPSBfLnRha2UgPSBmdW5jdGlvbihhcnJheSwgbiwgZ3VhcmQpIHsKICAgIGlmIChhcnJheSA9PSBudWxsKSByZXR1cm4gdm9pZCAwOwogICAgaWYgKG4gPT0gbnVsbCB8fCBndWFyZCkgcmV0dXJuIGFycmF5WzBdOwogICAgcmV0dXJuIF8uaW5pdGlhbChhcnJheSwgYXJyYXkubGVuZ3RoIC0gbik7CiAgfTsKCiAgLy8gUmV0dXJucyBldmVyeXRoaW5nIGJ1dCB0aGUgbGFzdCBlbnRyeSBvZiB0aGUgYXJyYXkuIEVzcGVjaWFsbHkgdXNlZnVsIG9uCiAgLy8gdGhlIGFyZ3VtZW50cyBvYmplY3QuIFBhc3NpbmcgKipuKiogd2lsbCByZXR1cm4gYWxsIHRoZSB2YWx1ZXMgaW4KICAvLyB0aGUgYXJyYXksIGV4Y2x1ZGluZyB0aGUgbGFzdCBOLgogIF8uaW5pdGlhbCA9IGZ1bmN0aW9uKGFycmF5LCBuLCBndWFyZCkgewogICAgcmV0dXJuIHNsaWNlLmNhbGwoYXJyYXksIDAsIE1hdGgubWF4KDAsIGFycmF5Lmxlbmd0aCAtIChuID09IG51bGwgfHwgZ3VhcmQgPyAxIDogbikpKTsKICB9OwoKICAvLyBHZXQgdGhlIGxhc3QgZWxlbWVudCBvZiBhbiBhcnJheS4gUGFzc2luZyAqKm4qKiB3aWxsIHJldHVybiB0aGUgbGFzdCBOCiAgLy8gdmFsdWVzIGluIHRoZSBhcnJheS4KICBfLmxhc3QgPSBmdW5jdGlvbihhcnJheSwgbiwgZ3VhcmQpIHsKICAgIGlmIChhcnJheSA9PSBudWxsKSByZXR1cm4gdm9pZCAwOwogICAgaWYgKG4gPT0gbnVsbCB8fCBndWFyZCkgcmV0dXJuIGFycmF5W2FycmF5Lmxlbmd0aCAtIDFdOwogICAgcmV0dXJuIF8ucmVzdChhcnJheSwgTWF0aC5tYXgoMCwgYXJyYXkubGVuZ3RoIC0gbikpOwogIH07CgogIC8vIFJldHVybnMgZXZlcnl0aGluZyBidXQgdGhlIGZpcnN0IGVudHJ5IG9mIHRoZSBhcnJheS4gQWxpYXNlZCBhcyBgdGFpbGAgYW5kIGBkcm9wYC4KICAvLyBFc3BlY2lhbGx5IHVzZWZ1bCBvbiB0aGUgYXJndW1lbnRzIG9iamVjdC4gUGFzc2luZyBhbiAqKm4qKiB3aWxsIHJldHVybgogIC8vIHRoZSByZXN0IE4gdmFsdWVzIGluIHRoZSBhcnJheS4KICBfLnJlc3QgPSBfLnRhaWwgPSBfLmRyb3AgPSBmdW5jdGlvbihhcnJheSwgbiwgZ3VhcmQpIHsKICAgIHJldHVybiBzbGljZS5jYWxsKGFycmF5LCBuID09IG51bGwgfHwgZ3VhcmQgPyAxIDogbik7CiAgfTsKCiAgLy8gVHJpbSBvdXQgYWxsIGZhbHN5IHZhbHVlcyBmcm9tIGFuIGFycmF5LgogIF8uY29tcGFjdCA9IGZ1bmN0aW9uKGFycmF5KSB7CiAgICByZXR1cm4gXy5maWx0ZXIoYXJyYXksIF8uaWRlbnRpdHkpOwogIH07CgogIC8vIEludGVybmFsIGltcGxlbWVudGF0aW9uIG9mIGEgcmVjdXJzaXZlIGBmbGF0dGVuYCBmdW5jdGlvbi4KICB2YXIgZmxhdHRlbiA9IGZ1bmN0aW9uKGlucHV0LCBzaGFsbG93LCBzdHJpY3QsIHN0YXJ0SW5kZXgpIHsKICAgIHZhciBvdXRwdXQgPSBbXSwgaWR4ID0gMDsKICAgIGZvciAodmFyIGkgPSBzdGFydEluZGV4IHx8IDAsIGxlbmd0aCA9IGdldExlbmd0aChpbnB1dCk7IGkgPCBsZW5ndGg7IGkrKykgewogICAgICB2YXIgdmFsdWUgPSBpbnB1dFtpXTsKICAgICAgaWYgKGlzQXJyYXlMaWtlKHZhbHVlKSAmJiAoXy5pc0FycmF5KHZhbHVlKSB8fCBfLmlzQXJndW1lbnRzKHZhbHVlKSkpIHsKICAgICAgICAvL2ZsYXR0ZW4gY3VycmVudCBsZXZlbCBvZiBhcnJheSBvciBhcmd1bWVudHMgb2JqZWN0CiAgICAgICAgaWYgKCFzaGFsbG93KSB2YWx1ZSA9IGZsYXR0ZW4odmFsdWUsIHNoYWxsb3csIHN0cmljdCk7CiAgICAgICAgdmFyIGogPSAwLCBsZW4gPSB2YWx1ZS5sZW5ndGg7CiAgICAgICAgb3V0cHV0Lmxlbmd0aCArPSBsZW47CiAgICAgICAgd2hpbGUgKGogPCBsZW4pIHsKICAgICAgICAgIG91dHB1dFtpZHgrK10gPSB2YWx1ZVtqKytdOwogICAgICAgIH0KICAgICAgfSBlbHNlIGlmICghc3RyaWN0KSB7CiAgICAgICAgb3V0cHV0W2lkeCsrXSA9IHZhbHVlOwogICAgICB9CiAgICB9CiAgICByZXR1cm4gb3V0cHV0OwogIH07CgogIC8vIEZsYXR0ZW4gb3V0IGFuIGFycmF5LCBlaXRoZXIgcmVjdXJzaXZlbHkgKGJ5IGRlZmF1bHQpLCBvciBqdXN0IG9uZSBsZXZlbC4KICBfLmZsYXR0ZW4gPSBmdW5jdGlvbihhcnJheSwgc2hhbGxvdykgewogICAgcmV0dXJuIGZsYXR0ZW4oYXJyYXksIHNoYWxsb3csIGZhbHNlKTsKICB9OwoKICAvLyBSZXR1cm4gYSB2ZXJzaW9uIG9mIHRoZSBhcnJheSB0aGF0IGRvZXMgbm90IGNvbnRhaW4gdGhlIHNwZWNpZmllZCB2YWx1ZShzKS4KICBfLndpdGhvdXQgPSBmdW5jdGlvbihhcnJheSkgewogICAgcmV0dXJuIF8uZGlmZmVyZW5jZShhcnJheSwgc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpKTsKICB9OwoKICAvLyBQcm9kdWNlIGEgZHVwbGljYXRlLWZyZWUgdmVyc2lvbiBvZiB0aGUgYXJyYXkuIElmIHRoZSBhcnJheSBoYXMgYWxyZWFkeQogIC8vIGJlZW4gc29ydGVkLCB5b3UgaGF2ZSB0aGUgb3B0aW9uIG9mIHVzaW5nIGEgZmFzdGVyIGFsZ29yaXRobS4KICAvLyBBbGlhc2VkIGFzIGB1bmlxdWVgLgogIF8udW5pcSA9IF8udW5pcXVlID0gZnVuY3Rpb24oYXJyYXksIGlzU29ydGVkLCBpdGVyYXRlZSwgY29udGV4dCkgewogICAgaWYgKCFfLmlzQm9vbGVhbihpc1NvcnRlZCkpIHsKICAgICAgY29udGV4dCA9IGl0ZXJhdGVlOwogICAgICBpdGVyYXRlZSA9IGlzU29ydGVkOwogICAgICBpc1NvcnRlZCA9IGZhbHNlOwogICAgfQogICAgaWYgKGl0ZXJhdGVlICE9IG51bGwpIGl0ZXJhdGVlID0gY2IoaXRlcmF0ZWUsIGNvbnRleHQpOwogICAgdmFyIHJlc3VsdCA9IFtdOwogICAgdmFyIHNlZW4gPSBbXTsKICAgIGZvciAodmFyIGkgPSAwLCBsZW5ndGggPSBnZXRMZW5ndGgoYXJyYXkpOyBpIDwgbGVuZ3RoOyBpKyspIHsKICAgICAgdmFyIHZhbHVlID0gYXJyYXlbaV0sCiAgICAgICAgICBjb21wdXRlZCA9IGl0ZXJhdGVlID8gaXRlcmF0ZWUodmFsdWUsIGksIGFycmF5KSA6IHZhbHVlOwogICAgICBpZiAoaXNTb3J0ZWQpIHsKICAgICAgICBpZiAoIWkgfHwgc2VlbiAhPT0gY29tcHV0ZWQpIHJlc3VsdC5wdXNoKHZhbHVlKTsKICAgICAgICBzZWVuID0gY29tcHV0ZWQ7CiAgICAgIH0gZWxzZSBpZiAoaXRlcmF0ZWUpIHsKICAgICAgICBpZiAoIV8uY29udGFpbnMoc2VlbiwgY29tcHV0ZWQpKSB7CiAgICAgICAgICBzZWVuLnB1c2goY29tcHV0ZWQpOwogICAgICAgICAgcmVzdWx0LnB1c2godmFsdWUpOwogICAgICAgIH0KICAgICAgfSBlbHNlIGlmICghXy5jb250YWlucyhyZXN1bHQsIHZhbHVlKSkgewogICAgICAgIHJlc3VsdC5wdXNoKHZhbHVlKTsKICAgICAgfQogICAgfQogICAgcmV0dXJuIHJlc3VsdDsKICB9OwoKICAvLyBQcm9kdWNlIGFuIGFycmF5IHRoYXQgY29udGFpbnMgdGhlIHVuaW9uOiBlYWNoIGRpc3RpbmN0IGVsZW1lbnQgZnJvbSBhbGwgb2YKICAvLyB0aGUgcGFzc2VkLWluIGFycmF5cy4KICBfLnVuaW9uID0gZnVuY3Rpb24oKSB7CiAgICByZXR1cm4gXy51bmlxKGZsYXR0ZW4oYXJndW1lbnRzLCB0cnVlLCB0cnVlKSk7CiAgfTsKCiAgLy8gUHJvZHVjZSBhbiBhcnJheSB0aGF0IGNvbnRhaW5zIGV2ZXJ5IGl0ZW0gc2hhcmVkIGJldHdlZW4gYWxsIHRoZQogIC8vIHBhc3NlZC1pbiBhcnJheXMuCiAgXy5pbnRlcnNlY3Rpb24gPSBmdW5jdGlvbihhcnJheSkgewogICAgdmFyIHJlc3VsdCA9IFtdOwogICAgdmFyIGFyZ3NMZW5ndGggPSBhcmd1bWVudHMubGVuZ3RoOwogICAgZm9yICh2YXIgaSA9IDAsIGxlbmd0aCA9IGdldExlbmd0aChhcnJheSk7IGkgPCBsZW5ndGg7IGkrKykgewogICAgICB2YXIgaXRlbSA9IGFycmF5W2ldOwogICAgICBpZiAoXy5jb250YWlucyhyZXN1bHQsIGl0ZW0pKSBjb250aW51ZTsKICAgICAgZm9yICh2YXIgaiA9IDE7IGogPCBhcmdzTGVuZ3RoOyBqKyspIHsKICAgICAgICBpZiAoIV8uY29udGFpbnMoYXJndW1lbnRzW2pdLCBpdGVtKSkgYnJlYWs7CiAgICAgIH0KICAgICAgaWYgKGogPT09IGFyZ3NMZW5ndGgpIHJlc3VsdC5wdXNoKGl0ZW0pOwogICAgfQogICAgcmV0dXJuIHJlc3VsdDsKICB9OwoKICAvLyBUYWtlIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gb25lIGFycmF5IGFuZCBhIG51bWJlciBvZiBvdGhlciBhcnJheXMuCiAgLy8gT25seSB0aGUgZWxlbWVudHMgcHJlc2VudCBpbiBqdXN0IHRoZSBmaXJzdCBhcnJheSB3aWxsIHJlbWFpbi4KICBfLmRpZmZlcmVuY2UgPSBmdW5jdGlvbihhcnJheSkgewogICAgdmFyIHJlc3QgPSBmbGF0dGVuKGFyZ3VtZW50cywgdHJ1ZSwgdHJ1ZSwgMSk7CiAgICByZXR1cm4gXy5maWx0ZXIoYXJyYXksIGZ1bmN0aW9uKHZhbHVlKXsKICAgICAgcmV0dXJuICFfLmNvbnRhaW5zKHJlc3QsIHZhbHVlKTsKICAgIH0pOwogIH07CgogIC8vIFppcCB0b2dldGhlciBtdWx0aXBsZSBsaXN0cyBpbnRvIGEgc2luZ2xlIGFycmF5IC0tIGVsZW1lbnRzIHRoYXQgc2hhcmUKICAvLyBhbiBpbmRleCBnbyB0b2dldGhlci4KICBfLnppcCA9IGZ1bmN0aW9uKCkgewogICAgcmV0dXJuIF8udW56aXAoYXJndW1lbnRzKTsKICB9OwoKICAvLyBDb21wbGVtZW50IG9mIF8uemlwLiBVbnppcCBhY2NlcHRzIGFuIGFycmF5IG9mIGFycmF5cyBhbmQgZ3JvdXBzCiAgLy8gZWFjaCBhcnJheSdzIGVsZW1lbnRzIG9uIHNoYXJlZCBpbmRpY2VzCiAgXy51bnppcCA9IGZ1bmN0aW9uKGFycmF5KSB7CiAgICB2YXIgbGVuZ3RoID0gYXJyYXkgJiYgXy5tYXgoYXJyYXksIGdldExlbmd0aCkubGVuZ3RoIHx8IDA7CiAgICB2YXIgcmVzdWx0ID0gQXJyYXkobGVuZ3RoKTsKCiAgICBmb3IgKHZhciBpbmRleCA9IDA7IGluZGV4IDwgbGVuZ3RoOyBpbmRleCsrKSB7CiAgICAgIHJlc3VsdFtpbmRleF0gPSBfLnBsdWNrKGFycmF5LCBpbmRleCk7CiAgICB9CiAgICByZXR1cm4gcmVzdWx0OwogIH07CgogIC8vIENvbnZlcnRzIGxpc3RzIGludG8gb2JqZWN0cy4gUGFzcyBlaXRoZXIgYSBzaW5nbGUgYXJyYXkgb2YgYFtrZXksIHZhbHVlXWAKICAvLyBwYWlycywgb3IgdHdvIHBhcmFsbGVsIGFycmF5cyBvZiB0aGUgc2FtZSBsZW5ndGggLS0gb25lIG9mIGtleXMsIGFuZCBvbmUgb2YKICAvLyB0aGUgY29ycmVzcG9uZGluZyB2YWx1ZXMuCiAgXy5vYmplY3QgPSBmdW5jdGlvbihsaXN0LCB2YWx1ZXMpIHsKICAgIHZhciByZXN1bHQgPSB7fTsKICAgIGZvciAodmFyIGkgPSAwLCBsZW5ndGggPSBnZXRMZW5ndGgobGlzdCk7IGkgPCBsZW5ndGg7IGkrKykgewogICAgICBpZiAodmFsdWVzKSB7CiAgICAgICAgcmVzdWx0W2xpc3RbaV1dID0gdmFsdWVzW2ldOwogICAgICB9IGVsc2UgewogICAgICAgIHJlc3VsdFtsaXN0W2ldWzBdXSA9IGxpc3RbaV1bMV07CiAgICAgIH0KICAgIH0KICAgIHJldHVybiByZXN1bHQ7CiAgfTsKCiAgLy8gR2VuZXJhdG9yIGZ1bmN0aW9uIHRvIGNyZWF0ZSB0aGUgZmluZEluZGV4IGFuZCBmaW5kTGFzdEluZGV4IGZ1bmN0aW9ucwogIGZ1bmN0aW9uIGNyZWF0ZVByZWRpY2F0ZUluZGV4RmluZGVyKGRpcikgewogICAgcmV0dXJuIGZ1bmN0aW9uKGFycmF5LCBwcmVkaWNhdGUsIGNvbnRleHQpIHsKICAgICAgcHJlZGljYXRlID0gY2IocHJlZGljYXRlLCBjb250ZXh0KTsKICAgICAgdmFyIGxlbmd0aCA9IGdldExlbmd0aChhcnJheSk7CiAgICAgIHZhciBpbmRleCA9IGRpciA+IDAgPyAwIDogbGVuZ3RoIC0gMTsKICAgICAgZm9yICg7IGluZGV4ID49IDAgJiYgaW5kZXggPCBsZW5ndGg7IGluZGV4ICs9IGRpcikgewogICAgICAgIGlmIChwcmVkaWNhdGUoYXJyYXlbaW5kZXhdLCBpbmRleCwgYXJyYXkpKSByZXR1cm4gaW5kZXg7CiAgICAgIH0KICAgICAgcmV0dXJuIC0xOwogICAgfTsKICB9CgogIC8vIFJldHVybnMgdGhlIGZpcnN0IGluZGV4IG9uIGFuIGFycmF5LWxpa2UgdGhhdCBwYXNzZXMgYSBwcmVkaWNhdGUgdGVzdAogIF8uZmluZEluZGV4ID0gY3JlYXRlUHJlZGljYXRlSW5kZXhGaW5kZXIoMSk7CiAgXy5maW5kTGFzdEluZGV4ID0gY3JlYXRlUHJlZGljYXRlSW5kZXhGaW5kZXIoLTEpOwoKICAvLyBVc2UgYSBjb21wYXJhdG9yIGZ1bmN0aW9uIHRvIGZpZ3VyZSBvdXQgdGhlIHNtYWxsZXN0IGluZGV4IGF0IHdoaWNoCiAgLy8gYW4gb2JqZWN0IHNob3VsZCBiZSBpbnNlcnRlZCBzbyBhcyB0byBtYWludGFpbiBvcmRlci4gVXNlcyBiaW5hcnkgc2VhcmNoLgogIF8uc29ydGVkSW5kZXggPSBmdW5jdGlvbihhcnJheSwgb2JqLCBpdGVyYXRlZSwgY29udGV4dCkgewogICAgaXRlcmF0ZWUgPSBjYihpdGVyYXRlZSwgY29udGV4dCwgMSk7CiAgICB2YXIgdmFsdWUgPSBpdGVyYXRlZShvYmopOwogICAgdmFyIGxvdyA9IDAsIGhpZ2ggPSBnZXRMZW5ndGgoYXJyYXkpOwogICAgd2hpbGUgKGxvdyA8IGhpZ2gpIHsKICAgICAgdmFyIG1pZCA9IE1hdGguZmxvb3IoKGxvdyArIGhpZ2gpIC8gMik7CiAgICAgIGlmIChpdGVyYXRlZShhcnJheVttaWRdKSA8IHZhbHVlKSBsb3cgPSBtaWQgKyAxOyBlbHNlIGhpZ2ggPSBtaWQ7CiAgICB9CiAgICByZXR1cm4gbG93OwogIH07CgogIC8vIEdlbmVyYXRvciBmdW5jdGlvbiB0byBjcmVhdGUgdGhlIGluZGV4T2YgYW5kIGxhc3RJbmRleE9mIGZ1bmN0aW9ucwogIGZ1bmN0aW9uIGNyZWF0ZUluZGV4RmluZGVyKGRpciwgcHJlZGljYXRlRmluZCwgc29ydGVkSW5kZXgpIHsKICAgIHJldHVybiBmdW5jdGlvbihhcnJheSwgaXRlbSwgaWR4KSB7CiAgICAgIHZhciBpID0gMCwgbGVuZ3RoID0gZ2V0TGVuZ3RoKGFycmF5KTsKICAgICAgaWYgKHR5cGVvZiBpZHggPT0gJ251bWJlcicpIHsKICAgICAgICBpZiAoZGlyID4gMCkgewogICAgICAgICAgICBpID0gaWR4ID49IDAgPyBpZHggOiBNYXRoLm1heChpZHggKyBsZW5ndGgsIGkpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgIGxlbmd0aCA9IGlkeCA+PSAwID8gTWF0aC5taW4oaWR4ICsgMSwgbGVuZ3RoKSA6IGlkeCArIGxlbmd0aCArIDE7CiAgICAgICAgfQogICAgICB9IGVsc2UgaWYgKHNvcnRlZEluZGV4ICYmIGlkeCAmJiBsZW5ndGgpIHsKICAgICAgICBpZHggPSBzb3J0ZWRJbmRleChhcnJheSwgaXRlbSk7CiAgICAgICAgcmV0dXJuIGFycmF5W2lkeF0gPT09IGl0ZW0gPyBpZHggOiAtMTsKICAgICAgfQogICAgICBpZiAoaXRlbSAhPT0gaXRlbSkgewogICAgICAgIGlkeCA9IHByZWRpY2F0ZUZpbmQoc2xpY2UuY2FsbChhcnJheSwgaSwgbGVuZ3RoKSwgXy5pc05hTik7CiAgICAgICAgcmV0dXJuIGlkeCA+PSAwID8gaWR4ICsgaSA6IC0xOwogICAgICB9CiAgICAgIGZvciAoaWR4ID0gZGlyID4gMCA/IGkgOiBsZW5ndGggLSAxOyBpZHggPj0gMCAmJiBpZHggPCBsZW5ndGg7IGlkeCArPSBkaXIpIHsKICAgICAgICBpZiAoYXJyYXlbaWR4XSA9PT0gaXRlbSkgcmV0dXJuIGlkeDsKICAgICAgfQogICAgICByZXR1cm4gLTE7CiAgICB9OwogIH0KCiAgLy8gUmV0dXJuIHRoZSBwb3NpdGlvbiBvZiB0aGUgZmlyc3Qgb2NjdXJyZW5jZSBvZiBhbiBpdGVtIGluIGFuIGFycmF5LAogIC8vIG9yIC0xIGlmIHRoZSBpdGVtIGlzIG5vdCBpbmNsdWRlZCBpbiB0aGUgYXJyYXkuCiAgLy8gSWYgdGhlIGFycmF5IGlzIGxhcmdlIGFuZCBhbHJlYWR5IGluIHNvcnQgb3JkZXIsIHBhc3MgYHRydWVgCiAgLy8gZm9yICoqaXNTb3J0ZWQqKiB0byB1c2UgYmluYXJ5IHNlYXJjaC4KICBfLmluZGV4T2YgPSBjcmVhdGVJbmRleEZpbmRlcigxLCBfLmZpbmRJbmRleCwgXy5zb3J0ZWRJbmRleCk7CiAgXy5sYXN0SW5kZXhPZiA9IGNyZWF0ZUluZGV4RmluZGVyKC0xLCBfLmZpbmRMYXN0SW5kZXgpOwoKICAvLyBHZW5lcmF0ZSBhbiBpbnRlZ2VyIEFycmF5IGNvbnRhaW5pbmcgYW4gYXJpdGhtZXRpYyBwcm9ncmVzc2lvbi4gQSBwb3J0IG9mCiAgLy8gdGhlIG5hdGl2ZSBQeXRob24gYHJhbmdlKClgIGZ1bmN0aW9uLiBTZWUKICAvLyBbdGhlIFB5dGhvbiBkb2N1bWVudGF0aW9uXShodHRwOi8vZG9jcy5weXRob24ub3JnL2xpYnJhcnkvZnVuY3Rpb25zLmh0bWwjcmFuZ2UpLgogIF8ucmFuZ2UgPSBmdW5jdGlvbihzdGFydCwgc3RvcCwgc3RlcCkgewogICAgaWYgKHN0b3AgPT0gbnVsbCkgewogICAgICBzdG9wID0gc3RhcnQgfHwgMDsKICAgICAgc3RhcnQgPSAwOwogICAgfQogICAgc3RlcCA9IHN0ZXAgfHwgMTsKCiAgICB2YXIgbGVuZ3RoID0gTWF0aC5tYXgoTWF0aC5jZWlsKChzdG9wIC0gc3RhcnQpIC8gc3RlcCksIDApOwogICAgdmFyIHJhbmdlID0gQXJyYXkobGVuZ3RoKTsKCiAgICBmb3IgKHZhciBpZHggPSAwOyBpZHggPCBsZW5ndGg7IGlkeCsrLCBzdGFydCArPSBzdGVwKSB7CiAgICAgIHJhbmdlW2lkeF0gPSBzdGFydDsKICAgIH0KCiAgICByZXR1cm4gcmFuZ2U7CiAgfTsKCiAgLy8gRnVuY3Rpb24gKGFoZW0pIEZ1bmN0aW9ucwogIC8vIC0tLS0tLS0tLS0tLS0tLS0tLQoKICAvLyBEZXRlcm1pbmVzIHdoZXRoZXIgdG8gZXhlY3V0ZSBhIGZ1bmN0aW9uIGFzIGEgY29uc3RydWN0b3IKICAvLyBvciBhIG5vcm1hbCBmdW5jdGlvbiB3aXRoIHRoZSBwcm92aWRlZCBhcmd1bWVudHMKICB2YXIgZXhlY3V0ZUJvdW5kID0gZnVuY3Rpb24oc291cmNlRnVuYywgYm91bmRGdW5jLCBjb250ZXh0LCBjYWxsaW5nQ29udGV4dCwgYXJncykgewogICAgaWYgKCEoY2FsbGluZ0NvbnRleHQgaW5zdGFuY2VvZiBib3VuZEZ1bmMpKSByZXR1cm4gc291cmNlRnVuYy5hcHBseShjb250ZXh0LCBhcmdzKTsKICAgIHZhciBzZWxmID0gYmFzZUNyZWF0ZShzb3VyY2VGdW5jLnByb3RvdHlwZSk7CiAgICB2YXIgcmVzdWx0ID0gc291cmNlRnVuYy5hcHBseShzZWxmLCBhcmdzKTsKICAgIGlmIChfLmlzT2JqZWN0KHJlc3VsdCkpIHJldHVybiByZXN1bHQ7CiAgICByZXR1cm4gc2VsZjsKICB9OwoKICAvLyBDcmVhdGUgYSBmdW5jdGlvbiBib3VuZCB0byBhIGdpdmVuIG9iamVjdCAoYXNzaWduaW5nIGB0aGlzYCwgYW5kIGFyZ3VtZW50cywKICAvLyBvcHRpb25hbGx5KS4gRGVsZWdhdGVzIHRvICoqRUNNQVNjcmlwdCA1KioncyBuYXRpdmUgYEZ1bmN0aW9uLmJpbmRgIGlmCiAgLy8gYXZhaWxhYmxlLgogIF8uYmluZCA9IGZ1bmN0aW9uKGZ1bmMsIGNvbnRleHQpIHsKICAgIGlmIChuYXRpdmVCaW5kICYmIGZ1bmMuYmluZCA9PT0gbmF0aXZlQmluZCkgcmV0dXJuIG5hdGl2ZUJpbmQuYXBwbHkoZnVuYywgc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpKTsKICAgIGlmICghXy5pc0Z1bmN0aW9uKGZ1bmMpKSB0aHJvdyBuZXcgVHlwZUVycm9yKCdCaW5kIG11c3QgYmUgY2FsbGVkIG9uIGEgZnVuY3Rpb24nKTsKICAgIHZhciBhcmdzID0gc2xpY2UuY2FsbChhcmd1bWVudHMsIDIpOwogICAgdmFyIGJvdW5kID0gZnVuY3Rpb24oKSB7CiAgICAgIHJldHVybiBleGVjdXRlQm91bmQoZnVuYywgYm91bmQsIGNvbnRleHQsIHRoaXMsIGFyZ3MuY29uY2F0KHNsaWNlLmNhbGwoYXJndW1lbnRzKSkpOwogICAgfTsKICAgIHJldHVybiBib3VuZDsKICB9OwoKICAvLyBQYXJ0aWFsbHkgYXBwbHkgYSBmdW5jdGlvbiBieSBjcmVhdGluZyBhIHZlcnNpb24gdGhhdCBoYXMgaGFkIHNvbWUgb2YgaXRzCiAgLy8gYXJndW1lbnRzIHByZS1maWxsZWQsIHdpdGhvdXQgY2hhbmdpbmcgaXRzIGR5bmFtaWMgYHRoaXNgIGNvbnRleHQuIF8gYWN0cwogIC8vIGFzIGEgcGxhY2Vob2xkZXIsIGFsbG93aW5nIGFueSBjb21iaW5hdGlvbiBvZiBhcmd1bWVudHMgdG8gYmUgcHJlLWZpbGxlZC4KICBfLnBhcnRpYWwgPSBmdW5jdGlvbihmdW5jKSB7CiAgICB2YXIgYm91bmRBcmdzID0gc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpOwogICAgdmFyIGJvdW5kID0gZnVuY3Rpb24oKSB7CiAgICAgIHZhciBwb3NpdGlvbiA9IDAsIGxlbmd0aCA9IGJvdW5kQXJncy5sZW5ndGg7CiAgICAgIHZhciBhcmdzID0gQXJyYXkobGVuZ3RoKTsKICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykgewogICAgICAgIGFyZ3NbaV0gPSBib3VuZEFyZ3NbaV0gPT09IF8gPyBhcmd1bWVudHNbcG9zaXRpb24rK10gOiBib3VuZEFyZ3NbaV07CiAgICAgIH0KICAgICAgd2hpbGUgKHBvc2l0aW9uIDwgYXJndW1lbnRzLmxlbmd0aCkgYXJncy5wdXNoKGFyZ3VtZW50c1twb3NpdGlvbisrXSk7CiAgICAgIHJldHVybiBleGVjdXRlQm91bmQoZnVuYywgYm91bmQsIHRoaXMsIHRoaXMsIGFyZ3MpOwogICAgfTsKICAgIHJldHVybiBib3VuZDsKICB9OwoKICAvLyBCaW5kIGEgbnVtYmVyIG9mIGFuIG9iamVjdCdzIG1ldGhvZHMgdG8gdGhhdCBvYmplY3QuIFJlbWFpbmluZyBhcmd1bWVudHMKICAvLyBhcmUgdGhlIG1ldGhvZCBuYW1lcyB0byBiZSBib3VuZC4gVXNlZnVsIGZvciBlbnN1cmluZyB0aGF0IGFsbCBjYWxsYmFja3MKICAvLyBkZWZpbmVkIG9uIGFuIG9iamVjdCBiZWxvbmcgdG8gaXQuCiAgXy5iaW5kQWxsID0gZnVuY3Rpb24ob2JqKSB7CiAgICB2YXIgaSwgbGVuZ3RoID0gYXJndW1lbnRzLmxlbmd0aCwga2V5OwogICAgaWYgKGxlbmd0aCA8PSAxKSB0aHJvdyBuZXcgRXJyb3IoJ2JpbmRBbGwgbXVzdCBiZSBwYXNzZWQgZnVuY3Rpb24gbmFtZXMnKTsKICAgIGZvciAoaSA9IDE7IGkgPCBsZW5ndGg7IGkrKykgewogICAgICBrZXkgPSBhcmd1bWVudHNbaV07CiAgICAgIG9ialtrZXldID0gXy5iaW5kKG9ialtrZXldLCBvYmopOwogICAgfQogICAgcmV0dXJuIG9iajsKICB9OwoKICAvLyBNZW1vaXplIGFuIGV4cGVuc2l2ZSBmdW5jdGlvbiBieSBzdG9yaW5nIGl0cyByZXN1bHRzLgogIF8ubWVtb2l6ZSA9IGZ1bmN0aW9uKGZ1bmMsIGhhc2hlcikgewogICAgdmFyIG1lbW9pemUgPSBmdW5jdGlvbihrZXkpIHsKICAgICAgdmFyIGNhY2hlID0gbWVtb2l6ZS5jYWNoZTsKICAgICAgdmFyIGFkZHJlc3MgPSAnJyArIChoYXNoZXIgPyBoYXNoZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKSA6IGtleSk7CiAgICAgIGlmICghXy5oYXMoY2FjaGUsIGFkZHJlc3MpKSBjYWNoZVthZGRyZXNzXSA9IGZ1bmMuYXBwbHkodGhpcywgYXJndW1lbnRzKTsKICAgICAgcmV0dXJuIGNhY2hlW2FkZHJlc3NdOwogICAgfTsKICAgIG1lbW9pemUuY2FjaGUgPSB7fTsKICAgIHJldHVybiBtZW1vaXplOwogIH07CgogIC8vIERlbGF5cyBhIGZ1bmN0aW9uIGZvciB0aGUgZ2l2ZW4gbnVtYmVyIG9mIG1pbGxpc2Vjb25kcywgYW5kIHRoZW4gY2FsbHMKICAvLyBpdCB3aXRoIHRoZSBhcmd1bWVudHMgc3VwcGxpZWQuCiAgXy5kZWxheSA9IGZ1bmN0aW9uKGZ1bmMsIHdhaXQpIHsKICAgIHZhciBhcmdzID0gc2xpY2UuY2FsbChhcmd1bWVudHMsIDIpOwogICAgcmV0dXJuIHNldFRpbWVvdXQoZnVuY3Rpb24oKXsKICAgICAgcmV0dXJuIGZ1bmMuYXBwbHkobnVsbCwgYXJncyk7CiAgICB9LCB3YWl0KTsKICB9OwoKICAvLyBEZWZlcnMgYSBmdW5jdGlvbiwgc2NoZWR1bGluZyBpdCB0byBydW4gYWZ0ZXIgdGhlIGN1cnJlbnQgY2FsbCBzdGFjayBoYXMKICAvLyBjbGVhcmVkLgogIF8uZGVmZXIgPSBfLnBhcnRpYWwoXy5kZWxheSwgXywgMSk7CgogIC8vIFJldHVybnMgYSBmdW5jdGlvbiwgdGhhdCwgd2hlbiBpbnZva2VkLCB3aWxsIG9ubHkgYmUgdHJpZ2dlcmVkIGF0IG1vc3Qgb25jZQogIC8vIGR1cmluZyBhIGdpdmVuIHdpbmRvdyBvZiB0aW1lLiBOb3JtYWxseSwgdGhlIHRocm90dGxlZCBmdW5jdGlvbiB3aWxsIHJ1bgogIC8vIGFzIG11Y2ggYXMgaXQgY2FuLCB3aXRob3V0IGV2ZXIgZ29pbmcgbW9yZSB0aGFuIG9uY2UgcGVyIGB3YWl0YCBkdXJhdGlvbjsKICAvLyBidXQgaWYgeW91J2QgbGlrZSB0byBkaXNhYmxlIHRoZSBleGVjdXRpb24gb24gdGhlIGxlYWRpbmcgZWRnZSwgcGFzcwogIC8vIGB7bGVhZGluZzogZmFsc2V9YC4gVG8gZGlzYWJsZSBleGVjdXRpb24gb24gdGhlIHRyYWlsaW5nIGVkZ2UsIGRpdHRvLgogIF8udGhyb3R0bGUgPSBmdW5jdGlvbihmdW5jLCB3YWl0LCBvcHRpb25zKSB7CiAgICB2YXIgY29udGV4dCwgYXJncywgcmVzdWx0OwogICAgdmFyIHRpbWVvdXQgPSBudWxsOwogICAgdmFyIHByZXZpb3VzID0gMDsKICAgIGlmICghb3B0aW9ucykgb3B0aW9ucyA9IHt9OwogICAgdmFyIGxhdGVyID0gZnVuY3Rpb24oKSB7CiAgICAgIHByZXZpb3VzID0gb3B0aW9ucy5sZWFkaW5nID09PSBmYWxzZSA/IDAgOiBfLm5vdygpOwogICAgICB0aW1lb3V0ID0gbnVsbDsKICAgICAgcmVzdWx0ID0gZnVuYy5hcHBseShjb250ZXh0LCBhcmdzKTsKICAgICAgaWYgKCF0aW1lb3V0KSBjb250ZXh0ID0gYXJncyA9IG51bGw7CiAgICB9OwogICAgcmV0dXJuIGZ1bmN0aW9uKCkgewogICAgICB2YXIgbm93ID0gXy5ub3coKTsKICAgICAgaWYgKCFwcmV2aW91cyAmJiBvcHRpb25zLmxlYWRpbmcgPT09IGZhbHNlKSBwcmV2aW91cyA9IG5vdzsKICAgICAgdmFyIHJlbWFpbmluZyA9IHdhaXQgLSAobm93IC0gcHJldmlvdXMpOwogICAgICBjb250ZXh0ID0gdGhpczsKICAgICAgYXJncyA9IGFyZ3VtZW50czsKICAgICAgaWYgKHJlbWFpbmluZyA8PSAwIHx8IHJlbWFpbmluZyA+IHdhaXQpIHsKICAgICAgICBpZiAodGltZW91dCkgewogICAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVvdXQpOwogICAgICAgICAgdGltZW91dCA9IG51bGw7CiAgICAgICAgfQogICAgICAgIHByZXZpb3VzID0gbm93OwogICAgICAgIHJlc3VsdCA9IGZ1bmMuYXBwbHkoY29udGV4dCwgYXJncyk7CiAgICAgICAgaWYgKCF0aW1lb3V0KSBjb250ZXh0ID0gYXJncyA9IG51bGw7CiAgICAgIH0gZWxzZSBpZiAoIXRpbWVvdXQgJiYgb3B0aW9ucy50cmFpbGluZyAhPT0gZmFsc2UpIHsKICAgICAgICB0aW1lb3V0ID0gc2V0VGltZW91dChsYXRlciwgcmVtYWluaW5nKTsKICAgICAgfQogICAgICByZXR1cm4gcmVzdWx0OwogICAgfTsKICB9OwoKICAvLyBSZXR1cm5zIGEgZnVuY3Rpb24sIHRoYXQsIGFzIGxvbmcgYXMgaXQgY29udGludWVzIHRvIGJlIGludm9rZWQsIHdpbGwgbm90CiAgLy8gYmUgdHJpZ2dlcmVkLiBUaGUgZnVuY3Rpb24gd2lsbCBiZSBjYWxsZWQgYWZ0ZXIgaXQgc3RvcHMgYmVpbmcgY2FsbGVkIGZvcgogIC8vIE4gbWlsbGlzZWNvbmRzLiBJZiBgaW1tZWRpYXRlYCBpcyBwYXNzZWQsIHRyaWdnZXIgdGhlIGZ1bmN0aW9uIG9uIHRoZQogIC8vIGxlYWRpbmcgZWRnZSwgaW5zdGVhZCBvZiB0aGUgdHJhaWxpbmcuCiAgXy5kZWJvdW5jZSA9IGZ1bmN0aW9uKGZ1bmMsIHdhaXQsIGltbWVkaWF0ZSkgewogICAgdmFyIHRpbWVvdXQsIGFyZ3MsIGNvbnRleHQsIHRpbWVzdGFtcCwgcmVzdWx0OwoKICAgIHZhciBsYXRlciA9IGZ1bmN0aW9uKCkgewogICAgICB2YXIgbGFzdCA9IF8ubm93KCkgLSB0aW1lc3RhbXA7CgogICAgICBpZiAobGFzdCA8IHdhaXQgJiYgbGFzdCA+PSAwKSB7CiAgICAgICAgdGltZW91dCA9IHNldFRpbWVvdXQobGF0ZXIsIHdhaXQgLSBsYXN0KTsKICAgICAgfSBlbHNlIHsKICAgICAgICB0aW1lb3V0ID0gbnVsbDsKICAgICAgICBpZiAoIWltbWVkaWF0ZSkgewogICAgICAgICAgcmVzdWx0ID0gZnVuYy5hcHBseShjb250ZXh0LCBhcmdzKTsKICAgICAgICAgIGlmICghdGltZW91dCkgY29udGV4dCA9IGFyZ3MgPSBudWxsOwogICAgICAgIH0KICAgICAgfQogICAgfTsKCiAgICByZXR1cm4gZnVuY3Rpb24oKSB7CiAgICAgIGNvbnRleHQgPSB0aGlzOwogICAgICBhcmdzID0gYXJndW1lbnRzOwogICAgICB0aW1lc3RhbXAgPSBfLm5vdygpOwogICAgICB2YXIgY2FsbE5vdyA9IGltbWVkaWF0ZSAmJiAhdGltZW91dDsKICAgICAgaWYgKCF0aW1lb3V0KSB0aW1lb3V0ID0gc2V0VGltZW91dChsYXRlciwgd2FpdCk7CiAgICAgIGlmIChjYWxsTm93KSB7CiAgICAgICAgcmVzdWx0ID0gZnVuYy5hcHBseShjb250ZXh0LCBhcmdzKTsKICAgICAgICBjb250ZXh0ID0gYXJncyA9IG51bGw7CiAgICAgIH0KCiAgICAgIHJldHVybiByZXN1bHQ7CiAgICB9OwogIH07CgogIC8vIFJldHVybnMgdGhlIGZpcnN0IGZ1bmN0aW9uIHBhc3NlZCBhcyBhbiBhcmd1bWVudCB0byB0aGUgc2Vjb25kLAogIC8vIGFsbG93aW5nIHlvdSB0byBhZGp1c3QgYXJndW1lbnRzLCBydW4gY29kZSBiZWZvcmUgYW5kIGFmdGVyLCBhbmQKICAvLyBjb25kaXRpb25hbGx5IGV4ZWN1dGUgdGhlIG9yaWdpbmFsIGZ1bmN0aW9uLgogIF8ud3JhcCA9IGZ1bmN0aW9uKGZ1bmMsIHdyYXBwZXIpIHsKICAgIHJldHVybiBfLnBhcnRpYWwod3JhcHBlciwgZnVuYyk7CiAgfTsKCiAgLy8gUmV0dXJucyBhIG5lZ2F0ZWQgdmVyc2lvbiBvZiB0aGUgcGFzc2VkLWluIHByZWRpY2F0ZS4KICBfLm5lZ2F0ZSA9IGZ1bmN0aW9uKHByZWRpY2F0ZSkgewogICAgcmV0dXJuIGZ1bmN0aW9uKCkgewogICAgICByZXR1cm4gIXByZWRpY2F0ZS5hcHBseSh0aGlzLCBhcmd1bWVudHMpOwogICAgfTsKICB9OwoKICAvLyBSZXR1cm5zIGEgZnVuY3Rpb24gdGhhdCBpcyB0aGUgY29tcG9zaXRpb24gb2YgYSBsaXN0IG9mIGZ1bmN0aW9ucywgZWFjaAogIC8vIGNvbnN1bWluZyB0aGUgcmV0dXJuIHZhbHVlIG9mIHRoZSBmdW5jdGlvbiB0aGF0IGZvbGxvd3MuCiAgXy5jb21wb3NlID0gZnVuY3Rpb24oKSB7CiAgICB2YXIgYXJncyA9IGFyZ3VtZW50czsKICAgIHZhciBzdGFydCA9IGFyZ3MubGVuZ3RoIC0gMTsKICAgIHJldHVybiBmdW5jdGlvbigpIHsKICAgICAgdmFyIGkgPSBzdGFydDsKICAgICAgdmFyIHJlc3VsdCA9IGFyZ3Nbc3RhcnRdLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7CiAgICAgIHdoaWxlIChpLS0pIHJlc3VsdCA9IGFyZ3NbaV0uY2FsbCh0aGlzLCByZXN1bHQpOwogICAgICByZXR1cm4gcmVzdWx0OwogICAgfTsKICB9OwoKICAvLyBSZXR1cm5zIGEgZnVuY3Rpb24gdGhhdCB3aWxsIG9ubHkgYmUgZXhlY3V0ZWQgb24gYW5kIGFmdGVyIHRoZSBOdGggY2FsbC4KICBfLmFmdGVyID0gZnVuY3Rpb24odGltZXMsIGZ1bmMpIHsKICAgIHJldHVybiBmdW5jdGlvbigpIHsKICAgICAgaWYgKC0tdGltZXMgPCAxKSB7CiAgICAgICAgcmV0dXJuIGZ1bmMuYXBwbHkodGhpcywgYXJndW1lbnRzKTsKICAgICAgfQogICAgfTsKICB9OwoKICAvLyBSZXR1cm5zIGEgZnVuY3Rpb24gdGhhdCB3aWxsIG9ubHkgYmUgZXhlY3V0ZWQgdXAgdG8gKGJ1dCBub3QgaW5jbHVkaW5nKSB0aGUgTnRoIGNhbGwuCiAgXy5iZWZvcmUgPSBmdW5jdGlvbih0aW1lcywgZnVuYykgewogICAgdmFyIG1lbW87CiAgICByZXR1cm4gZnVuY3Rpb24oKSB7CiAgICAgIGlmICgtLXRpbWVzID4gMCkgewogICAgICAgIG1lbW8gPSBmdW5jLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7CiAgICAgIH0KICAgICAgaWYgKHRpbWVzIDw9IDEpIGZ1bmMgPSBudWxsOwogICAgICByZXR1cm4gbWVtbzsKICAgIH07CiAgfTsKCiAgLy8gUmV0dXJucyBhIGZ1bmN0aW9uIHRoYXQgd2lsbCBiZSBleGVjdXRlZCBhdCBtb3N0IG9uZSB0aW1lLCBubyBtYXR0ZXIgaG93CiAgLy8gb2Z0ZW4geW91IGNhbGwgaXQuIFVzZWZ1bCBmb3IgbGF6eSBpbml0aWFsaXphdGlvbi4KICBfLm9uY2UgPSBfLnBhcnRpYWwoXy5iZWZvcmUsIDIpOwoKICAvLyBPYmplY3QgRnVuY3Rpb25zCiAgLy8gLS0tLS0tLS0tLS0tLS0tLQoKICAvLyBLZXlzIGluIElFIDwgOSB0aGF0IHdvbid0IGJlIGl0ZXJhdGVkIGJ5IGBmb3Iga2V5IGluIC4uLmAgYW5kIHRodXMgbWlzc2VkLgogIHZhciBoYXNFbnVtQnVnID0gIXt0b1N0cmluZzogbnVsbH0ucHJvcGVydHlJc0VudW1lcmFibGUoJ3RvU3RyaW5nJyk7CiAgdmFyIG5vbkVudW1lcmFibGVQcm9wcyA9IFsndmFsdWVPZicsICdpc1Byb3RvdHlwZU9mJywgJ3RvU3RyaW5nJywKICAgICAgICAgICAgICAgICAgICAgICdwcm9wZXJ0eUlzRW51bWVyYWJsZScsICdoYXNPd25Qcm9wZXJ0eScsICd0b0xvY2FsZVN0cmluZyddOwoKICBmdW5jdGlvbiBjb2xsZWN0Tm9uRW51bVByb3BzKG9iaiwga2V5cykgewogICAgdmFyIG5vbkVudW1JZHggPSBub25FbnVtZXJhYmxlUHJvcHMubGVuZ3RoOwogICAgdmFyIGNvbnN0cnVjdG9yID0gb2JqLmNvbnN0cnVjdG9yOwogICAgdmFyIHByb3RvID0gKF8uaXNGdW5jdGlvbihjb25zdHJ1Y3RvcikgJiYgY29uc3RydWN0b3IucHJvdG90eXBlKSB8fCBPYmpQcm90bzsKCiAgICAvLyBDb25zdHJ1Y3RvciBpcyBhIHNwZWNpYWwgY2FzZS4KICAgIHZhciBwcm9wID0gJ2NvbnN0cnVjdG9yJzsKICAgIGlmIChfLmhhcyhvYmosIHByb3ApICYmICFfLmNvbnRhaW5zKGtleXMsIHByb3ApKSBrZXlzLnB1c2gocHJvcCk7CgogICAgd2hpbGUgKG5vbkVudW1JZHgtLSkgewogICAgICBwcm9wID0gbm9uRW51bWVyYWJsZVByb3BzW25vbkVudW1JZHhdOwogICAgICBpZiAocHJvcCBpbiBvYmogJiYgb2JqW3Byb3BdICE9PSBwcm90b1twcm9wXSAmJiAhXy5jb250YWlucyhrZXlzLCBwcm9wKSkgewogICAgICAgIGtleXMucHVzaChwcm9wKTsKICAgICAgfQogICAgfQogIH0KCiAgLy8gUmV0cmlldmUgdGhlIG5hbWVzIG9mIGFuIG9iamVjdCdzIG93biBwcm9wZXJ0aWVzLgogIC8vIERlbGVnYXRlcyB0byAqKkVDTUFTY3JpcHQgNSoqJ3MgbmF0aXZlIGBPYmplY3Qua2V5c2AKICBfLmtleXMgPSBmdW5jdGlvbihvYmopIHsKICAgIGlmICghXy5pc09iamVjdChvYmopKSByZXR1cm4gW107CiAgICBpZiAobmF0aXZlS2V5cykgcmV0dXJuIG5hdGl2ZUtleXMob2JqKTsKICAgIHZhciBrZXlzID0gW107CiAgICBmb3IgKHZhciBrZXkgaW4gb2JqKSBpZiAoXy5oYXMob2JqLCBrZXkpKSBrZXlzLnB1c2goa2V5KTsKICAgIC8vIEFoZW0sIElFIDwgOS4KICAgIGlmIChoYXNFbnVtQnVnKSBjb2xsZWN0Tm9uRW51bVByb3BzKG9iaiwga2V5cyk7CiAgICByZXR1cm4ga2V5czsKICB9OwoKICAvLyBSZXRyaWV2ZSBhbGwgdGhlIHByb3BlcnR5IG5hbWVzIG9mIGFuIG9iamVjdC4KICBfLmFsbEtleXMgPSBmdW5jdGlvbihvYmopIHsKICAgIGlmICghXy5pc09iamVjdChvYmopKSByZXR1cm4gW107CiAgICB2YXIga2V5cyA9IFtdOwogICAgZm9yICh2YXIga2V5IGluIG9iaikga2V5cy5wdXNoKGtleSk7CiAgICAvLyBBaGVtLCBJRSA8IDkuCiAgICBpZiAoaGFzRW51bUJ1ZykgY29sbGVjdE5vbkVudW1Qcm9wcyhvYmosIGtleXMpOwogICAgcmV0dXJuIGtleXM7CiAgfTsKCiAgLy8gUmV0cmlldmUgdGhlIHZhbHVlcyBvZiBhbiBvYmplY3QncyBwcm9wZXJ0aWVzLgogIF8udmFsdWVzID0gZnVuY3Rpb24ob2JqKSB7CiAgICB2YXIga2V5cyA9IF8ua2V5cyhvYmopOwogICAgdmFyIGxlbmd0aCA9IGtleXMubGVuZ3RoOwogICAgdmFyIHZhbHVlcyA9IEFycmF5KGxlbmd0aCk7CiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7CiAgICAgIHZhbHVlc1tpXSA9IG9ialtrZXlzW2ldXTsKICAgIH0KICAgIHJldHVybiB2YWx1ZXM7CiAgfTsKCiAgLy8gUmV0dXJucyB0aGUgcmVzdWx0cyBvZiBhcHBseWluZyB0aGUgaXRlcmF0ZWUgdG8gZWFjaCBlbGVtZW50IG9mIHRoZSBvYmplY3QKICAvLyBJbiBjb250cmFzdCB0byBfLm1hcCBpdCByZXR1cm5zIGFuIG9iamVjdAogIF8ubWFwT2JqZWN0ID0gZnVuY3Rpb24ob2JqLCBpdGVyYXRlZSwgY29udGV4dCkgewogICAgaXRlcmF0ZWUgPSBjYihpdGVyYXRlZSwgY29udGV4dCk7CiAgICB2YXIga2V5cyA9ICBfLmtleXMob2JqKSwKICAgICAgICAgIGxlbmd0aCA9IGtleXMubGVuZ3RoLAogICAgICAgICAgcmVzdWx0cyA9IHt9LAogICAgICAgICAgY3VycmVudEtleTsKICAgICAgZm9yICh2YXIgaW5kZXggPSAwOyBpbmRleCA8IGxlbmd0aDsgaW5kZXgrKykgewogICAgICAgIGN1cnJlbnRLZXkgPSBrZXlzW2luZGV4XTsKICAgICAgICByZXN1bHRzW2N1cnJlbnRLZXldID0gaXRlcmF0ZWUob2JqW2N1cnJlbnRLZXldLCBjdXJyZW50S2V5LCBvYmopOwogICAgICB9CiAgICAgIHJldHVybiByZXN1bHRzOwogIH07CgogIC8vIENvbnZlcnQgYW4gb2JqZWN0IGludG8gYSBsaXN0IG9mIGBba2V5LCB2YWx1ZV1gIHBhaXJzLgogIF8ucGFpcnMgPSBmdW5jdGlvbihvYmopIHsKICAgIHZhciBrZXlzID0gXy5rZXlzKG9iaik7CiAgICB2YXIgbGVuZ3RoID0ga2V5cy5sZW5ndGg7CiAgICB2YXIgcGFpcnMgPSBBcnJheShsZW5ndGgpOwogICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykgewogICAgICBwYWlyc1tpXSA9IFtrZXlzW2ldLCBvYmpba2V5c1tpXV1dOwogICAgfQogICAgcmV0dXJuIHBhaXJzOwogIH07CgogIC8vIEludmVydCB0aGUga2V5cyBhbmQgdmFsdWVzIG9mIGFuIG9iamVjdC4gVGhlIHZhbHVlcyBtdXN0IGJlIHNlcmlhbGl6YWJsZS4KICBfLmludmVydCA9IGZ1bmN0aW9uKG9iaikgewogICAgdmFyIHJlc3VsdCA9IHt9OwogICAgdmFyIGtleXMgPSBfLmtleXMob2JqKTsKICAgIGZvciAodmFyIGkgPSAwLCBsZW5ndGggPSBrZXlzLmxlbmd0aDsgaSA8IGxlbmd0aDsgaSsrKSB7CiAgICAgIHJlc3VsdFtvYmpba2V5c1tpXV1dID0ga2V5c1tpXTsKICAgIH0KICAgIHJldHVybiByZXN1bHQ7CiAgfTsKCiAgLy8gUmV0dXJuIGEgc29ydGVkIGxpc3Qgb2YgdGhlIGZ1bmN0aW9uIG5hbWVzIGF2YWlsYWJsZSBvbiB0aGUgb2JqZWN0LgogIC8vIEFsaWFzZWQgYXMgYG1ldGhvZHNgCiAgXy5mdW5jdGlvbnMgPSBfLm1ldGhvZHMgPSBmdW5jdGlvbihvYmopIHsKICAgIHZhciBuYW1lcyA9IFtdOwogICAgZm9yICh2YXIga2V5IGluIG9iaikgewogICAgICBpZiAoXy5pc0Z1bmN0aW9uKG9ialtrZXldKSkgbmFtZXMucHVzaChrZXkpOwogICAgfQogICAgcmV0dXJuIG5hbWVzLnNvcnQoKTsKICB9OwoKICAvLyBFeHRlbmQgYSBnaXZlbiBvYmplY3Qgd2l0aCBhbGwgdGhlIHByb3BlcnRpZXMgaW4gcGFzc2VkLWluIG9iamVjdChzKS4KICBfLmV4dGVuZCA9IGNyZWF0ZUFzc2lnbmVyKF8uYWxsS2V5cyk7CgogIC8vIEFzc2lnbnMgYSBnaXZlbiBvYmplY3Qgd2l0aCBhbGwgdGhlIG93biBwcm9wZXJ0aWVzIGluIHRoZSBwYXNzZWQtaW4gb2JqZWN0KHMpCiAgLy8gKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2RvY3MvV2ViL0phdmFTY3JpcHQvUmVmZXJlbmNlL0dsb2JhbF9PYmplY3RzL09iamVjdC9hc3NpZ24pCiAgXy5leHRlbmRPd24gPSBfLmFzc2lnbiA9IGNyZWF0ZUFzc2lnbmVyKF8ua2V5cyk7CgogIC8vIFJldHVybnMgdGhlIGZpcnN0IGtleSBvbiBhbiBvYmplY3QgdGhhdCBwYXNzZXMgYSBwcmVkaWNhdGUgdGVzdAogIF8uZmluZEtleSA9IGZ1bmN0aW9uKG9iaiwgcHJlZGljYXRlLCBjb250ZXh0KSB7CiAgICBwcmVkaWNhdGUgPSBjYihwcmVkaWNhdGUsIGNvbnRleHQpOwogICAgdmFyIGtleXMgPSBfLmtleXMob2JqKSwga2V5OwogICAgZm9yICh2YXIgaSA9IDAsIGxlbmd0aCA9IGtleXMubGVuZ3RoOyBpIDwgbGVuZ3RoOyBpKyspIHsKICAgICAga2V5ID0ga2V5c1tpXTsKICAgICAgaWYgKHByZWRpY2F0ZShvYmpba2V5XSwga2V5LCBvYmopKSByZXR1cm4ga2V5OwogICAgfQogIH07CgogIC8vIFJldHVybiBhIGNvcHkgb2YgdGhlIG9iamVjdCBvbmx5IGNvbnRhaW5pbmcgdGhlIHdoaXRlbGlzdGVkIHByb3BlcnRpZXMuCiAgXy5waWNrID0gZnVuY3Rpb24ob2JqZWN0LCBvaXRlcmF0ZWUsIGNvbnRleHQpIHsKICAgIHZhciByZXN1bHQgPSB7fSwgb2JqID0gb2JqZWN0LCBpdGVyYXRlZSwga2V5czsKICAgIGlmIChvYmogPT0gbnVsbCkgcmV0dXJuIHJlc3VsdDsKICAgIGlmIChfLmlzRnVuY3Rpb24ob2l0ZXJhdGVlKSkgewogICAgICBrZXlzID0gXy5hbGxLZXlzKG9iaik7CiAgICAgIGl0ZXJhdGVlID0gb3B0aW1pemVDYihvaXRlcmF0ZWUsIGNvbnRleHQpOwogICAgfSBlbHNlIHsKICAgICAga2V5cyA9IGZsYXR0ZW4oYXJndW1lbnRzLCBmYWxzZSwgZmFsc2UsIDEpOwogICAgICBpdGVyYXRlZSA9IGZ1bmN0aW9uKHZhbHVlLCBrZXksIG9iaikgeyByZXR1cm4ga2V5IGluIG9iajsgfTsKICAgICAgb2JqID0gT2JqZWN0KG9iaik7CiAgICB9CiAgICBmb3IgKHZhciBpID0gMCwgbGVuZ3RoID0ga2V5cy5sZW5ndGg7IGkgPCBsZW5ndGg7IGkrKykgewogICAgICB2YXIga2V5ID0ga2V5c1tpXTsKICAgICAgdmFyIHZhbHVlID0gb2JqW2tleV07CiAgICAgIGlmIChpdGVyYXRlZSh2YWx1ZSwga2V5LCBvYmopKSByZXN1bHRba2V5XSA9IHZhbHVlOwogICAgfQogICAgcmV0dXJuIHJlc3VsdDsKICB9OwoKICAgLy8gUmV0dXJuIGEgY29weSBvZiB0aGUgb2JqZWN0IHdpdGhvdXQgdGhlIGJsYWNrbGlzdGVkIHByb3BlcnRpZXMuCiAgXy5vbWl0ID0gZnVuY3Rpb24ob2JqLCBpdGVyYXRlZSwgY29udGV4dCkgewogICAgaWYgKF8uaXNGdW5jdGlvbihpdGVyYXRlZSkpIHsKICAgICAgaXRlcmF0ZWUgPSBfLm5lZ2F0ZShpdGVyYXRlZSk7CiAgICB9IGVsc2UgewogICAgICB2YXIga2V5cyA9IF8ubWFwKGZsYXR0ZW4oYXJndW1lbnRzLCBmYWxzZSwgZmFsc2UsIDEpLCBTdHJpbmcpOwogICAgICBpdGVyYXRlZSA9IGZ1bmN0aW9uKHZhbHVlLCBrZXkpIHsKICAgICAgICByZXR1cm4gIV8uY29udGFpbnMoa2V5cywga2V5KTsKICAgICAgfTsKICAgIH0KICAgIHJldHVybiBfLnBpY2sob2JqLCBpdGVyYXRlZSwgY29udGV4dCk7CiAgfTsKCiAgLy8gRmlsbCBpbiBhIGdpdmVuIG9iamVjdCB3aXRoIGRlZmF1bHQgcHJvcGVydGllcy4KICBfLmRlZmF1bHRzID0gY3JlYXRlQXNzaWduZXIoXy5hbGxLZXlzLCB0cnVlKTsKCiAgLy8gQ3JlYXRlcyBhbiBvYmplY3QgdGhhdCBpbmhlcml0cyBmcm9tIHRoZSBnaXZlbiBwcm90b3R5cGUgb2JqZWN0LgogIC8vIElmIGFkZGl0aW9uYWwgcHJvcGVydGllcyBhcmUgcHJvdmlkZWQgdGhlbiB0aGV5IHdpbGwgYmUgYWRkZWQgdG8gdGhlCiAgLy8gY3JlYXRlZCBvYmplY3QuCiAgXy5jcmVhdGUgPSBmdW5jdGlvbihwcm90b3R5cGUsIHByb3BzKSB7CiAgICB2YXIgcmVzdWx0ID0gYmFzZUNyZWF0ZShwcm90b3R5cGUpOwogICAgaWYgKHByb3BzKSBfLmV4dGVuZE93bihyZXN1bHQsIHByb3BzKTsKICAgIHJldHVybiByZXN1bHQ7CiAgfTsKCiAgLy8gQ3JlYXRlIGEgKHNoYWxsb3ctY2xvbmVkKSBkdXBsaWNhdGUgb2YgYW4gb2JqZWN0LgogIF8uY2xvbmUgPSBmdW5jdGlvbihvYmopIHsKICAgIGlmICghXy5pc09iamVjdChvYmopKSByZXR1cm4gb2JqOwogICAgcmV0dXJuIF8uaXNBcnJheShvYmopID8gb2JqLnNsaWNlKCkgOiBfLmV4dGVuZCh7fSwgb2JqKTsKICB9OwoKICAvLyBJbnZva2VzIGludGVyY2VwdG9yIHdpdGggdGhlIG9iaiwgYW5kIHRoZW4gcmV0dXJucyBvYmouCiAgLy8gVGhlIHByaW1hcnkgcHVycG9zZSBvZiB0aGlzIG1ldGhvZCBpcyB0byAidGFwIGludG8iIGEgbWV0aG9kIGNoYWluLCBpbgogIC8vIG9yZGVyIHRvIHBlcmZvcm0gb3BlcmF0aW9ucyBvbiBpbnRlcm1lZGlhdGUgcmVzdWx0cyB3aXRoaW4gdGhlIGNoYWluLgogIF8udGFwID0gZnVuY3Rpb24ob2JqLCBpbnRlcmNlcHRvcikgewogICAgaW50ZXJjZXB0b3Iob2JqKTsKICAgIHJldHVybiBvYmo7CiAgfTsKCiAgLy8gUmV0dXJucyB3aGV0aGVyIGFuIG9iamVjdCBoYXMgYSBnaXZlbiBzZXQgb2YgYGtleTp2YWx1ZWAgcGFpcnMuCiAgXy5pc01hdGNoID0gZnVuY3Rpb24ob2JqZWN0LCBhdHRycykgewogICAgdmFyIGtleXMgPSBfLmtleXMoYXR0cnMpLCBsZW5ndGggPSBrZXlzLmxlbmd0aDsKICAgIGlmIChvYmplY3QgPT0gbnVsbCkgcmV0dXJuICFsZW5ndGg7CiAgICB2YXIgb2JqID0gT2JqZWN0KG9iamVjdCk7CiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7CiAgICAgIHZhciBrZXkgPSBrZXlzW2ldOwogICAgICBpZiAoYXR0cnNba2V5XSAhPT0gb2JqW2tleV0gfHwgIShrZXkgaW4gb2JqKSkgcmV0dXJuIGZhbHNlOwogICAgfQogICAgcmV0dXJuIHRydWU7CiAgfTsKCgogIC8vIEludGVybmFsIHJlY3Vyc2l2ZSBjb21wYXJpc29uIGZ1bmN0aW9uIGZvciBgaXNFcXVhbGAuCiAgdmFyIGVxID0gZnVuY3Rpb24oYSwgYiwgYVN0YWNrLCBiU3RhY2spIHsKICAgIC8vIElkZW50aWNhbCBvYmplY3RzIGFyZSBlcXVhbC4gYDAgPT09IC0wYCwgYnV0IHRoZXkgYXJlbid0IGlkZW50aWNhbC4KICAgIC8vIFNlZSB0aGUgW0hhcm1vbnkgYGVnYWxgIHByb3Bvc2FsXShodHRwOi8vd2lraS5lY21hc2NyaXB0Lm9yZy9kb2t1LnBocD9pZD1oYXJtb255OmVnYWwpLgogICAgaWYgKGEgPT09IGIpIHJldHVybiBhICE9PSAwIHx8IDEgLyBhID09PSAxIC8gYjsKICAgIC8vIEEgc3RyaWN0IGNvbXBhcmlzb24gaXMgbmVjZXNzYXJ5IGJlY2F1c2UgYG51bGwgPT0gdW5kZWZpbmVkYC4KICAgIGlmIChhID09IG51bGwgfHwgYiA9PSBudWxsKSByZXR1cm4gYSA9PT0gYjsKICAgIC8vIFVud3JhcCBhbnkgd3JhcHBlZCBvYmplY3RzLgogICAgaWYgKGEgaW5zdGFuY2VvZiBfKSBhID0gYS5fd3JhcHBlZDsKICAgIGlmIChiIGluc3RhbmNlb2YgXykgYiA9IGIuX3dyYXBwZWQ7CiAgICAvLyBDb21wYXJlIGBbW0NsYXNzXV1gIG5hbWVzLgogICAgdmFyIGNsYXNzTmFtZSA9IHRvU3RyaW5nLmNhbGwoYSk7CiAgICBpZiAoY2xhc3NOYW1lICE9PSB0b1N0cmluZy5jYWxsKGIpKSByZXR1cm4gZmFsc2U7CiAgICBzd2l0Y2ggKGNsYXNzTmFtZSkgewogICAgICAvLyBTdHJpbmdzLCBudW1iZXJzLCByZWd1bGFyIGV4cHJlc3Npb25zLCBkYXRlcywgYW5kIGJvb2xlYW5zIGFyZSBjb21wYXJlZCBieSB2YWx1ZS4KICAgICAgY2FzZSAnW29iamVjdCBSZWdFeHBdJzoKICAgICAgLy8gUmVnRXhwcyBhcmUgY29lcmNlZCB0byBzdHJpbmdzIGZvciBjb21wYXJpc29uIChOb3RlOiAnJyArIC9hL2kgPT09ICcvYS9pJykKICAgICAgY2FzZSAnW29iamVjdCBTdHJpbmddJzoKICAgICAgICAvLyBQcmltaXRpdmVzIGFuZCB0aGVpciBjb3JyZXNwb25kaW5nIG9iamVjdCB3cmFwcGVycyBhcmUgZXF1aXZhbGVudDsgdGh1cywgYCI1ImAgaXMKICAgICAgICAvLyBlcXVpdmFsZW50IHRvIGBuZXcgU3RyaW5nKCI1IilgLgogICAgICAgIHJldHVybiAnJyArIGEgPT09ICcnICsgYjsKICAgICAgY2FzZSAnW29iamVjdCBOdW1iZXJdJzoKICAgICAgICAvLyBgTmFOYHMgYXJlIGVxdWl2YWxlbnQsIGJ1dCBub24tcmVmbGV4aXZlLgogICAgICAgIC8vIE9iamVjdChOYU4pIGlzIGVxdWl2YWxlbnQgdG8gTmFOCiAgICAgICAgaWYgKCthICE9PSArYSkgcmV0dXJuICtiICE9PSArYjsKICAgICAgICAvLyBBbiBgZWdhbGAgY29tcGFyaXNvbiBpcyBwZXJmb3JtZWQgZm9yIG90aGVyIG51bWVyaWMgdmFsdWVzLgogICAgICAgIHJldHVybiArYSA9PT0gMCA/IDEgLyArYSA9PT0gMSAvIGIgOiArYSA9PT0gK2I7CiAgICAgIGNhc2UgJ1tvYmplY3QgRGF0ZV0nOgogICAgICBjYXNlICdbb2JqZWN0IEJvb2xlYW5dJzoKICAgICAgICAvLyBDb2VyY2UgZGF0ZXMgYW5kIGJvb2xlYW5zIHRvIG51bWVyaWMgcHJpbWl0aXZlIHZhbHVlcy4gRGF0ZXMgYXJlIGNvbXBhcmVkIGJ5IHRoZWlyCiAgICAgICAgLy8gbWlsbGlzZWNvbmQgcmVwcmVzZW50YXRpb25zLiBOb3RlIHRoYXQgaW52YWxpZCBkYXRlcyB3aXRoIG1pbGxpc2Vjb25kIHJlcHJlc2VudGF0aW9ucwogICAgICAgIC8vIG9mIGBOYU5gIGFyZSBub3QgZXF1aXZhbGVudC4KICAgICAgICByZXR1cm4gK2EgPT09ICtiOwogICAgfQoKICAgIHZhciBhcmVBcnJheXMgPSBjbGFzc05hbWUgPT09ICdbb2JqZWN0IEFycmF5XSc7CiAgICBpZiAoIWFyZUFycmF5cykgewogICAgICBpZiAodHlwZW9mIGEgIT0gJ29iamVjdCcgfHwgdHlwZW9mIGIgIT0gJ29iamVjdCcpIHJldHVybiBmYWxzZTsKCiAgICAgIC8vIE9iamVjdHMgd2l0aCBkaWZmZXJlbnQgY29uc3RydWN0b3JzIGFyZSBub3QgZXF1aXZhbGVudCwgYnV0IGBPYmplY3RgcyBvciBgQXJyYXlgcwogICAgICAvLyBmcm9tIGRpZmZlcmVudCBmcmFtZXMgYXJlLgogICAgICB2YXIgYUN0b3IgPSBhLmNvbnN0cnVjdG9yLCBiQ3RvciA9IGIuY29uc3RydWN0b3I7CiAgICAgIGlmIChhQ3RvciAhPT0gYkN0b3IgJiYgIShfLmlzRnVuY3Rpb24oYUN0b3IpICYmIGFDdG9yIGluc3RhbmNlb2YgYUN0b3IgJiYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIF8uaXNGdW5jdGlvbihiQ3RvcikgJiYgYkN0b3IgaW5zdGFuY2VvZiBiQ3RvcikKICAgICAgICAgICAgICAgICAgICAgICAgICAmJiAoJ2NvbnN0cnVjdG9yJyBpbiBhICYmICdjb25zdHJ1Y3RvcicgaW4gYikpIHsKICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgIH0KICAgIC8vIEFzc3VtZSBlcXVhbGl0eSBmb3IgY3ljbGljIHN0cnVjdHVyZXMuIFRoZSBhbGdvcml0aG0gZm9yIGRldGVjdGluZyBjeWNsaWMKICAgIC8vIHN0cnVjdHVyZXMgaXMgYWRhcHRlZCBmcm9tIEVTIDUuMSBzZWN0aW9uIDE1LjEyLjMsIGFic3RyYWN0IG9wZXJhdGlvbiBgSk9gLgoKICAgIC8vIEluaXRpYWxpemluZyBzdGFjayBvZiB0cmF2ZXJzZWQgb2JqZWN0cy4KICAgIC8vIEl0J3MgZG9uZSBoZXJlIHNpbmNlIHdlIG9ubHkgbmVlZCB0aGVtIGZvciBvYmplY3RzIGFuZCBhcnJheXMgY29tcGFyaXNvbi4KICAgIGFTdGFjayA9IGFTdGFjayB8fCBbXTsKICAgIGJTdGFjayA9IGJTdGFjayB8fCBbXTsKICAgIHZhciBsZW5ndGggPSBhU3RhY2subGVuZ3RoOwogICAgd2hpbGUgKGxlbmd0aC0tKSB7CiAgICAgIC8vIExpbmVhciBzZWFyY2guIFBlcmZvcm1hbmNlIGlzIGludmVyc2VseSBwcm9wb3J0aW9uYWwgdG8gdGhlIG51bWJlciBvZgogICAgICAvLyB1bmlxdWUgbmVzdGVkIHN0cnVjdHVyZXMuCiAgICAgIGlmIChhU3RhY2tbbGVuZ3RoXSA9PT0gYSkgcmV0dXJuIGJTdGFja1tsZW5ndGhdID09PSBiOwogICAgfQoKICAgIC8vIEFkZCB0aGUgZmlyc3Qgb2JqZWN0IHRvIHRoZSBzdGFjayBvZiB0cmF2ZXJzZWQgb2JqZWN0cy4KICAgIGFTdGFjay5wdXNoKGEpOwogICAgYlN0YWNrLnB1c2goYik7CgogICAgLy8gUmVjdXJzaXZlbHkgY29tcGFyZSBvYmplY3RzIGFuZCBhcnJheXMuCiAgICBpZiAoYXJlQXJyYXlzKSB7CiAgICAgIC8vIENvbXBhcmUgYXJyYXkgbGVuZ3RocyB0byBkZXRlcm1pbmUgaWYgYSBkZWVwIGNvbXBhcmlzb24gaXMgbmVjZXNzYXJ5LgogICAgICBsZW5ndGggPSBhLmxlbmd0aDsKICAgICAgaWYgKGxlbmd0aCAhPT0gYi5sZW5ndGgpIHJldHVybiBmYWxzZTsKICAgICAgLy8gRGVlcCBjb21wYXJlIHRoZSBjb250ZW50cywgaWdub3Jpbmcgbm9uLW51bWVyaWMgcHJvcGVydGllcy4KICAgICAgd2hpbGUgKGxlbmd0aC0tKSB7CiAgICAgICAgaWYgKCFlcShhW2xlbmd0aF0sIGJbbGVuZ3RoXSwgYVN0YWNrLCBiU3RhY2spKSByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgIC8vIERlZXAgY29tcGFyZSBvYmplY3RzLgogICAgICB2YXIga2V5cyA9IF8ua2V5cyhhKSwga2V5OwogICAgICBsZW5ndGggPSBrZXlzLmxlbmd0aDsKICAgICAgLy8gRW5zdXJlIHRoYXQgYm90aCBvYmplY3RzIGNvbnRhaW4gdGhlIHNhbWUgbnVtYmVyIG9mIHByb3BlcnRpZXMgYmVmb3JlIGNvbXBhcmluZyBkZWVwIGVxdWFsaXR5LgogICAgICBpZiAoXy5rZXlzKGIpLmxlbmd0aCAhPT0gbGVuZ3RoKSByZXR1cm4gZmFsc2U7CiAgICAgIHdoaWxlIChsZW5ndGgtLSkgewogICAgICAgIC8vIERlZXAgY29tcGFyZSBlYWNoIG1lbWJlcgogICAgICAgIGtleSA9IGtleXNbbGVuZ3RoXTsKICAgICAgICBpZiAoIShfLmhhcyhiLCBrZXkpICYmIGVxKGFba2V5XSwgYltrZXldLCBhU3RhY2ssIGJTdGFjaykpKSByZXR1cm4gZmFsc2U7CiAgICAgIH0KICAgIH0KICAgIC8vIFJlbW92ZSB0aGUgZmlyc3Qgb2JqZWN0IGZyb20gdGhlIHN0YWNrIG9mIHRyYXZlcnNlZCBvYmplY3RzLgogICAgYVN0YWNrLnBvcCgpOwogICAgYlN0YWNrLnBvcCgpOwogICAgcmV0dXJuIHRydWU7CiAgfTsKCiAgLy8gUGVyZm9ybSBhIGRlZXAgY29tcGFyaXNvbiB0byBjaGVjayBpZiB0d28gb2JqZWN0cyBhcmUgZXF1YWwuCiAgXy5pc0VxdWFsID0gZnVuY3Rpb24oYSwgYikgewogICAgcmV0dXJuIGVxKGEsIGIpOwogIH07CgogIC8vIElzIGEgZ2l2ZW4gYXJyYXksIHN0cmluZywgb3Igb2JqZWN0IGVtcHR5PwogIC8vIEFuICJlbXB0eSIgb2JqZWN0IGhhcyBubyBlbnVtZXJhYmxlIG93bi1wcm9wZXJ0aWVzLgogIF8uaXNFbXB0eSA9IGZ1bmN0aW9uKG9iaikgewogICAgaWYgKG9iaiA9PSBudWxsKSByZXR1cm4gdHJ1ZTsKICAgIGlmIChpc0FycmF5TGlrZShvYmopICYmIChfLmlzQXJyYXkob2JqKSB8fCBfLmlzU3RyaW5nKG9iaikgfHwgXy5pc0FyZ3VtZW50cyhvYmopKSkgcmV0dXJuIG9iai5sZW5ndGggPT09IDA7CiAgICByZXR1cm4gXy5rZXlzKG9iaikubGVuZ3RoID09PSAwOwogIH07CgogIC8vIElzIGEgZ2l2ZW4gdmFsdWUgYSBET00gZWxlbWVudD8KICBfLmlzRWxlbWVudCA9IGZ1bmN0aW9uKG9iaikgewogICAgcmV0dXJuICEhKG9iaiAmJiBvYmoubm9kZVR5cGUgPT09IDEpOwogIH07CgogIC8vIElzIGEgZ2l2ZW4gdmFsdWUgYW4gYXJyYXk/CiAgLy8gRGVsZWdhdGVzIHRvIEVDTUE1J3MgbmF0aXZlIEFycmF5LmlzQXJyYXkKICBfLmlzQXJyYXkgPSBuYXRpdmVJc0FycmF5IHx8IGZ1bmN0aW9uKG9iaikgewogICAgcmV0dXJuIHRvU3RyaW5nLmNhbGwob2JqKSA9PT0gJ1tvYmplY3QgQXJyYXldJzsKICB9OwoKICAvLyBJcyBhIGdpdmVuIHZhcmlhYmxlIGFuIG9iamVjdD8KICBfLmlzT2JqZWN0ID0gZnVuY3Rpb24ob2JqKSB7CiAgICB2YXIgdHlwZSA9IHR5cGVvZiBvYmo7CiAgICByZXR1cm4gdHlwZSA9PT0gJ2Z1bmN0aW9uJyB8fCB0eXBlID09PSAnb2JqZWN0JyAmJiAhIW9iajsKICB9OwoKICAvLyBBZGQgc29tZSBpc1R5cGUgbWV0aG9kczogaXNBcmd1bWVudHMsIGlzRnVuY3Rpb24sIGlzU3RyaW5nLCBpc051bWJlciwgaXNEYXRlLCBpc1JlZ0V4cCwgaXNFcnJvci4KICBfLmVhY2goWydBcmd1bWVudHMnLCAnRnVuY3Rpb24nLCAnU3RyaW5nJywgJ051bWJlcicsICdEYXRlJywgJ1JlZ0V4cCcsICdFcnJvciddLCBmdW5jdGlvbihuYW1lKSB7CiAgICBfWydpcycgKyBuYW1lXSA9IGZ1bmN0aW9uKG9iaikgewogICAgICByZXR1cm4gdG9TdHJpbmcuY2FsbChvYmopID09PSAnW29iamVjdCAnICsgbmFtZSArICddJzsKICAgIH07CiAgfSk7CgogIC8vIERlZmluZSBhIGZhbGxiYWNrIHZlcnNpb24gb2YgdGhlIG1ldGhvZCBpbiBicm93c2VycyAoYWhlbSwgSUUgPCA5KSwgd2hlcmUKICAvLyB0aGVyZSBpc24ndCBhbnkgaW5zcGVjdGFibGUgIkFyZ3VtZW50cyIgdHlwZS4KICBpZiAoIV8uaXNBcmd1bWVudHMoYXJndW1lbnRzKSkgewogICAgXy5pc0FyZ3VtZW50cyA9IGZ1bmN0aW9uKG9iaikgewogICAgICByZXR1cm4gXy5oYXMob2JqLCAnY2FsbGVlJyk7CiAgICB9OwogIH0KCiAgLy8gT3B0aW1pemUgYGlzRnVuY3Rpb25gIGlmIGFwcHJvcHJpYXRlLiBXb3JrIGFyb3VuZCBzb21lIHR5cGVvZiBidWdzIGluIG9sZCB2OCwKICAvLyBJRSAxMSAoIzE2MjEpLCBhbmQgaW4gU2FmYXJpIDggKCMxOTI5KS4KICBpZiAodHlwZW9mIC8uLyAhPSAnZnVuY3Rpb24nICYmIHR5cGVvZiBJbnQ4QXJyYXkgIT0gJ29iamVjdCcpIHsKICAgIF8uaXNGdW5jdGlvbiA9IGZ1bmN0aW9uKG9iaikgewogICAgICByZXR1cm4gdHlwZW9mIG9iaiA9PSAnZnVuY3Rpb24nIHx8IGZhbHNlOwogICAgfTsKICB9CgogIC8vIElzIGEgZ2l2ZW4gb2JqZWN0IGEgZmluaXRlIG51bWJlcj8KICBfLmlzRmluaXRlID0gZnVuY3Rpb24ob2JqKSB7CiAgICByZXR1cm4gaXNGaW5pdGUob2JqKSAmJiAhaXNOYU4ocGFyc2VGbG9hdChvYmopKTsKICB9OwoKICAvLyBJcyB0aGUgZ2l2ZW4gdmFsdWUgYE5hTmA/IChOYU4gaXMgdGhlIG9ubHkgbnVtYmVyIHdoaWNoIGRvZXMgbm90IGVxdWFsIGl0c2VsZikuCiAgXy5pc05hTiA9IGZ1bmN0aW9uKG9iaikgewogICAgcmV0dXJuIF8uaXNOdW1iZXIob2JqKSAmJiBvYmogIT09ICtvYmo7CiAgfTsKCiAgLy8gSXMgYSBnaXZlbiB2YWx1ZSBhIGJvb2xlYW4/CiAgXy5pc0Jvb2xlYW4gPSBmdW5jdGlvbihvYmopIHsKICAgIHJldHVybiBvYmogPT09IHRydWUgfHwgb2JqID09PSBmYWxzZSB8fCB0b1N0cmluZy5jYWxsKG9iaikgPT09ICdbb2JqZWN0IEJvb2xlYW5dJzsKICB9OwoKICAvLyBJcyBhIGdpdmVuIHZhbHVlIGVxdWFsIHRvIG51bGw/CiAgXy5pc051bGwgPSBmdW5jdGlvbihvYmopIHsKICAgIHJldHVybiBvYmogPT09IG51bGw7CiAgfTsKCiAgLy8gSXMgYSBnaXZlbiB2YXJpYWJsZSB1bmRlZmluZWQ/CiAgXy5pc1VuZGVmaW5lZCA9IGZ1bmN0aW9uKG9iaikgewogICAgcmV0dXJuIG9iaiA9PT0gdm9pZCAwOwogIH07CgogIC8vIFNob3J0Y3V0IGZ1bmN0aW9uIGZvciBjaGVja2luZyBpZiBhbiBvYmplY3QgaGFzIGEgZ2l2ZW4gcHJvcGVydHkgZGlyZWN0bHkKICAvLyBvbiBpdHNlbGYgKGluIG90aGVyIHdvcmRzLCBub3Qgb24gYSBwcm90b3R5cGUpLgogIF8uaGFzID0gZnVuY3Rpb24ob2JqLCBrZXkpIHsKICAgIHJldHVybiBvYmogIT0gbnVsbCAmJiBoYXNPd25Qcm9wZXJ0eS5jYWxsKG9iaiwga2V5KTsKICB9OwoKICAvLyBVdGlsaXR5IEZ1bmN0aW9ucwogIC8vIC0tLS0tLS0tLS0tLS0tLS0tCgogIC8vIFJ1biBVbmRlcnNjb3JlLmpzIGluICpub0NvbmZsaWN0KiBtb2RlLCByZXR1cm5pbmcgdGhlIGBfYCB2YXJpYWJsZSB0byBpdHMKICAvLyBwcmV2aW91cyBvd25lci4gUmV0dXJucyBhIHJlZmVyZW5jZSB0byB0aGUgVW5kZXJzY29yZSBvYmplY3QuCiAgXy5ub0NvbmZsaWN0ID0gZnVuY3Rpb24oKSB7CiAgICByb290Ll8gPSBwcmV2aW91c1VuZGVyc2NvcmU7CiAgICByZXR1cm4gdGhpczsKICB9OwoKICAvLyBLZWVwIHRoZSBpZGVudGl0eSBmdW5jdGlvbiBhcm91bmQgZm9yIGRlZmF1bHQgaXRlcmF0ZWVzLgogIF8uaWRlbnRpdHkgPSBmdW5jdGlvbih2YWx1ZSkgewogICAgcmV0dXJuIHZhbHVlOwogIH07CgogIC8vIFByZWRpY2F0ZS1nZW5lcmF0aW5nIGZ1bmN0aW9ucy4gT2Z0ZW4gdXNlZnVsIG91dHNpZGUgb2YgVW5kZXJzY29yZS4KICBfLmNvbnN0YW50ID0gZnVuY3Rpb24odmFsdWUpIHsKICAgIHJldHVybiBmdW5jdGlvbigpIHsKICAgICAgcmV0dXJuIHZhbHVlOwogICAgfTsKICB9OwoKICBfLm5vb3AgPSBmdW5jdGlvbigpe307CgogIF8ucHJvcGVydHkgPSBwcm9wZXJ0eTsKCiAgLy8gR2VuZXJhdGVzIGEgZnVuY3Rpb24gZm9yIGEgZ2l2ZW4gb2JqZWN0IHRoYXQgcmV0dXJucyBhIGdpdmVuIHByb3BlcnR5LgogIF8ucHJvcGVydHlPZiA9IGZ1bmN0aW9uKG9iaikgewogICAgcmV0dXJuIG9iaiA9PSBudWxsID8gZnVuY3Rpb24oKXt9IDogZnVuY3Rpb24oa2V5KSB7CiAgICAgIHJldHVybiBvYmpba2V5XTsKICAgIH07CiAgfTsKCiAgLy8gUmV0dXJucyBhIHByZWRpY2F0ZSBmb3IgY2hlY2tpbmcgd2hldGhlciBhbiBvYmplY3QgaGFzIGEgZ2l2ZW4gc2V0IG9mCiAgLy8gYGtleTp2YWx1ZWAgcGFpcnMuCiAgXy5tYXRjaGVyID0gXy5tYXRjaGVzID0gZnVuY3Rpb24oYXR0cnMpIHsKICAgIGF0dHJzID0gXy5leHRlbmRPd24oe30sIGF0dHJzKTsKICAgIHJldHVybiBmdW5jdGlvbihvYmopIHsKICAgICAgcmV0dXJuIF8uaXNNYXRjaChvYmosIGF0dHJzKTsKICAgIH07CiAgfTsKCiAgLy8gUnVuIGEgZnVuY3Rpb24gKipuKiogdGltZXMuCiAgXy50aW1lcyA9IGZ1bmN0aW9uKG4sIGl0ZXJhdGVlLCBjb250ZXh0KSB7CiAgICB2YXIgYWNjdW0gPSBBcnJheShNYXRoLm1heCgwLCBuKSk7CiAgICBpdGVyYXRlZSA9IG9wdGltaXplQ2IoaXRlcmF0ZWUsIGNvbnRleHQsIDEpOwogICAgZm9yICh2YXIgaSA9IDA7IGkgPCBuOyBpKyspIGFjY3VtW2ldID0gaXRlcmF0ZWUoaSk7CiAgICByZXR1cm4gYWNjdW07CiAgfTsKCiAgLy8gUmV0dXJuIGEgcmFuZG9tIGludGVnZXIgYmV0d2VlbiBtaW4gYW5kIG1heCAoaW5jbHVzaXZlKS4KICBfLnJhbmRvbSA9IGZ1bmN0aW9uKG1pbiwgbWF4KSB7CiAgICBpZiAobWF4ID09IG51bGwpIHsKICAgICAgbWF4ID0gbWluOwogICAgICBtaW4gPSAwOwogICAgfQogICAgcmV0dXJuIG1pbiArIE1hdGguZmxvb3IoTWF0aC5yYW5kb20oKSAqIChtYXggLSBtaW4gKyAxKSk7CiAgfTsKCiAgLy8gQSAocG9zc2libHkgZmFzdGVyKSB3YXkgdG8gZ2V0IHRoZSBjdXJyZW50IHRpbWVzdGFtcCBhcyBhbiBpbnRlZ2VyLgogIF8ubm93ID0gRGF0ZS5ub3cgfHwgZnVuY3Rpb24oKSB7CiAgICByZXR1cm4gbmV3IERhdGUoKS5nZXRUaW1lKCk7CiAgfTsKCiAgIC8vIExpc3Qgb2YgSFRNTCBlbnRpdGllcyBmb3IgZXNjYXBpbmcuCiAgdmFyIGVzY2FwZU1hcCA9IHsKICAgICcmJzogJyZhbXA7JywKICAgICc8JzogJyZsdDsnLAogICAgJz4nOiAnJmd0OycsCiAgICAnIic6ICcmcXVvdDsnLAogICAgIiciOiAnJiN4Mjc7JywKICAgICdgJzogJyYjeDYwOycKICB9OwogIHZhciB1bmVzY2FwZU1hcCA9IF8uaW52ZXJ0KGVzY2FwZU1hcCk7CgogIC8vIEZ1bmN0aW9ucyBmb3IgZXNjYXBpbmcgYW5kIHVuZXNjYXBpbmcgc3RyaW5ncyB0by9mcm9tIEhUTUwgaW50ZXJwb2xhdGlvbi4KICB2YXIgY3JlYXRlRXNjYXBlciA9IGZ1bmN0aW9uKG1hcCkgewogICAgdmFyIGVzY2FwZXIgPSBmdW5jdGlvbihtYXRjaCkgewogICAgICByZXR1cm4gbWFwW21hdGNoXTsKICAgIH07CiAgICAvLyBSZWdleGVzIGZvciBpZGVudGlmeWluZyBhIGtleSB0aGF0IG5lZWRzIHRvIGJlIGVzY2FwZWQKICAgIHZhciBzb3VyY2UgPSAnKD86JyArIF8ua2V5cyhtYXApLmpvaW4oJ3wnKSArICcpJzsKICAgIHZhciB0ZXN0UmVnZXhwID0gUmVnRXhwKHNvdXJjZSk7CiAgICB2YXIgcmVwbGFjZVJlZ2V4cCA9IFJlZ0V4cChzb3VyY2UsICdnJyk7CiAgICByZXR1cm4gZnVuY3Rpb24oc3RyaW5nKSB7CiAgICAgIHN0cmluZyA9IHN0cmluZyA9PSBudWxsID8gJycgOiAnJyArIHN0cmluZzsKICAgICAgcmV0dXJuIHRlc3RSZWdleHAudGVzdChzdHJpbmcpID8gc3RyaW5nLnJlcGxhY2UocmVwbGFjZVJlZ2V4cCwgZXNjYXBlcikgOiBzdHJpbmc7CiAgICB9OwogIH07CiAgXy5lc2NhcGUgPSBjcmVhdGVFc2NhcGVyKGVzY2FwZU1hcCk7CiAgXy51bmVzY2FwZSA9IGNyZWF0ZUVzY2FwZXIodW5lc2NhcGVNYXApOwoKICAvLyBJZiB0aGUgdmFsdWUgb2YgdGhlIG5hbWVkIGBwcm9wZXJ0eWAgaXMgYSBmdW5jdGlvbiB0aGVuIGludm9rZSBpdCB3aXRoIHRoZQogIC8vIGBvYmplY3RgIGFzIGNvbnRleHQ7IG90aGVyd2lzZSwgcmV0dXJuIGl0LgogIF8ucmVzdWx0ID0gZnVuY3Rpb24ob2JqZWN0LCBwcm9wZXJ0eSwgZmFsbGJhY2spIHsKICAgIHZhciB2YWx1ZSA9IG9iamVjdCA9PSBudWxsID8gdm9pZCAwIDogb2JqZWN0W3Byb3BlcnR5XTsKICAgIGlmICh2YWx1ZSA9PT0gdm9pZCAwKSB7CiAgICAgIHZhbHVlID0gZmFsbGJhY2s7CiAgICB9CiAgICByZXR1cm4gXy5pc0Z1bmN0aW9uKHZhbHVlKSA/IHZhbHVlLmNhbGwob2JqZWN0KSA6IHZhbHVlOwogIH07CgogIC8vIEdlbmVyYXRlIGEgdW5pcXVlIGludGVnZXIgaWQgKHVuaXF1ZSB3aXRoaW4gdGhlIGVudGlyZSBjbGllbnQgc2Vzc2lvbikuCiAgLy8gVXNlZnVsIGZvciB0ZW1wb3JhcnkgRE9NIGlkcy4KICB2YXIgaWRDb3VudGVyID0gMDsKICBfLnVuaXF1ZUlkID0gZnVuY3Rpb24ocHJlZml4KSB7CiAgICB2YXIgaWQgPSArK2lkQ291bnRlciArICcnOwogICAgcmV0dXJuIHByZWZpeCA/IHByZWZpeCArIGlkIDogaWQ7CiAgfTsKCiAgLy8gQnkgZGVmYXVsdCwgVW5kZXJzY29yZSB1c2VzIEVSQi1zdHlsZSB0ZW1wbGF0ZSBkZWxpbWl0ZXJzLCBjaGFuZ2UgdGhlCiAgLy8gZm9sbG93aW5nIHRlbXBsYXRlIHNldHRpbmdzIHRvIHVzZSBhbHRlcm5hdGl2ZSBkZWxpbWl0ZXJzLgogIF8udGVtcGxhdGVTZXR0aW5ncyA9IHsKICAgIGV2YWx1YXRlICAgIDogLzwlKFtcc1xTXSs/KSU+L2csCiAgICBpbnRlcnBvbGF0ZSA6IC88JT0oW1xzXFNdKz8pJT4vZywKICAgIGVzY2FwZSAgICAgIDogLzwlLShbXHNcU10rPyklPi9nCiAgfTsKCiAgLy8gV2hlbiBjdXN0b21pemluZyBgdGVtcGxhdGVTZXR0aW5nc2AsIGlmIHlvdSBkb24ndCB3YW50IHRvIGRlZmluZSBhbgogIC8vIGludGVycG9sYXRpb24sIGV2YWx1YXRpb24gb3IgZXNjYXBpbmcgcmVnZXgsIHdlIG5lZWQgb25lIHRoYXQgaXMKICAvLyBndWFyYW50ZWVkIG5vdCB0byBtYXRjaC4KICB2YXIgbm9NYXRjaCA9IC8oLileLzsKCiAgLy8gQ2VydGFpbiBjaGFyYWN0ZXJzIG5lZWQgdG8gYmUgZXNjYXBlZCBzbyB0aGF0IHRoZXkgY2FuIGJlIHB1dCBpbnRvIGEKICAvLyBzdHJpbmcgbGl0ZXJhbC4KICB2YXIgZXNjYXBlcyA9IHsKICAgICInIjogICAgICAiJyIsCiAgICAnXFwnOiAgICAgJ1xcJywKICAgICdccic6ICAgICAncicsCiAgICAnXG4nOiAgICAgJ24nLAogICAgJ1x1MjAyOCc6ICd1MjAyOCcsCiAgICAnXHUyMDI5JzogJ3UyMDI5JwogIH07CgogIHZhciBlc2NhcGVyID0gL1xcfCd8XHJ8XG58XHUyMDI4fFx1MjAyOS9nOwoKICB2YXIgZXNjYXBlQ2hhciA9IGZ1bmN0aW9uKG1hdGNoKSB7CiAgICByZXR1cm4gJ1xcJyArIGVzY2FwZXNbbWF0Y2hdOwogIH07CgogIC8vIEphdmFTY3JpcHQgbWljcm8tdGVtcGxhdGluZywgc2ltaWxhciB0byBKb2huIFJlc2lnJ3MgaW1wbGVtZW50YXRpb24uCiAgLy8gVW5kZXJzY29yZSB0ZW1wbGF0aW5nIGhhbmRsZXMgYXJiaXRyYXJ5IGRlbGltaXRlcnMsIHByZXNlcnZlcyB3aGl0ZXNwYWNlLAogIC8vIGFuZCBjb3JyZWN0bHkgZXNjYXBlcyBxdW90ZXMgd2l0aGluIGludGVycG9sYXRlZCBjb2RlLgogIC8vIE5COiBgb2xkU2V0dGluZ3NgIG9ubHkgZXhpc3RzIGZvciBiYWNrd2FyZHMgY29tcGF0aWJpbGl0eS4KICBfLnRlbXBsYXRlID0gZnVuY3Rpb24odGV4dCwgc2V0dGluZ3MsIG9sZFNldHRpbmdzKSB7CiAgICBpZiAoIXNldHRpbmdzICYmIG9sZFNldHRpbmdzKSBzZXR0aW5ncyA9IG9sZFNldHRpbmdzOwogICAgc2V0dGluZ3MgPSBfLmRlZmF1bHRzKHt9LCBzZXR0aW5ncywgXy50ZW1wbGF0ZVNldHRpbmdzKTsKCiAgICAvLyBDb21iaW5lIGRlbGltaXRlcnMgaW50byBvbmUgcmVndWxhciBleHByZXNzaW9uIHZpYSBhbHRlcm5hdGlvbi4KICAgIHZhciBtYXRjaGVyID0gUmVnRXhwKFsKICAgICAgKHNldHRpbmdzLmVzY2FwZSB8fCBub01hdGNoKS5zb3VyY2UsCiAgICAgIChzZXR0aW5ncy5pbnRlcnBvbGF0ZSB8fCBub01hdGNoKS5zb3VyY2UsCiAgICAgIChzZXR0aW5ncy5ldmFsdWF0ZSB8fCBub01hdGNoKS5zb3VyY2UKICAgIF0uam9pbignfCcpICsgJ3wkJywgJ2cnKTsKCiAgICAvLyBDb21waWxlIHRoZSB0ZW1wbGF0ZSBzb3VyY2UsIGVzY2FwaW5nIHN0cmluZyBsaXRlcmFscyBhcHByb3ByaWF0ZWx5LgogICAgdmFyIGluZGV4ID0gMDsKICAgIHZhciBzb3VyY2UgPSAiX19wKz0nIjsKICAgIHRleHQucmVwbGFjZShtYXRjaGVyLCBmdW5jdGlvbihtYXRjaCwgZXNjYXBlLCBpbnRlcnBvbGF0ZSwgZXZhbHVhdGUsIG9mZnNldCkgewogICAgICBzb3VyY2UgKz0gdGV4dC5zbGljZShpbmRleCwgb2Zmc2V0KS5yZXBsYWNlKGVzY2FwZXIsIGVzY2FwZUNoYXIpOwogICAgICBpbmRleCA9IG9mZnNldCArIG1hdGNoLmxlbmd0aDsKCiAgICAgIGlmIChlc2NhcGUpIHsKICAgICAgICBzb3VyY2UgKz0gIicrXG4oKF9fdD0oIiArIGVzY2FwZSArICIpKT09bnVsbD8nJzpfLmVzY2FwZShfX3QpKStcbiciOwogICAgICB9IGVsc2UgaWYgKGludGVycG9sYXRlKSB7CiAgICAgICAgc291cmNlICs9ICInK1xuKChfX3Q9KCIgKyBpbnRlcnBvbGF0ZSArICIpKT09bnVsbD8nJzpfX3QpK1xuJyI7CiAgICAgIH0gZWxzZSBpZiAoZXZhbHVhdGUpIHsKICAgICAgICBzb3VyY2UgKz0gIic7XG4iICsgZXZhbHVhdGUgKyAiXG5fX3ArPSciOwogICAgICB9CgogICAgICAvLyBBZG9iZSBWTXMgbmVlZCB0aGUgbWF0Y2ggcmV0dXJuZWQgdG8gcHJvZHVjZSB0aGUgY29ycmVjdCBvZmZlc3QuCiAgICAgIHJldHVybiBtYXRjaDsKICAgIH0pOwogICAgc291cmNlICs9ICInO1xuIjsKCiAgICAvLyBJZiBhIHZhcmlhYmxlIGlzIG5vdCBzcGVjaWZpZWQsIHBsYWNlIGRhdGEgdmFsdWVzIGluIGxvY2FsIHNjb3BlLgogICAgaWYgKCFzZXR0aW5ncy52YXJpYWJsZSkgc291cmNlID0gJ3dpdGgob2JqfHx7fSl7XG4nICsgc291cmNlICsgJ31cbic7CgogICAgc291cmNlID0gInZhciBfX3QsX19wPScnLF9faj1BcnJheS5wcm90b3R5cGUuam9pbiwiICsKICAgICAgInByaW50PWZ1bmN0aW9uKCl7X19wKz1fX2ouY2FsbChhcmd1bWVudHMsJycpO307XG4iICsKICAgICAgc291cmNlICsgJ3JldHVybiBfX3A7XG4nOwoKICAgIHRyeSB7CiAgICAgIHZhciByZW5kZXIgPSBuZXcgRnVuY3Rpb24oc2V0dGluZ3MudmFyaWFibGUgfHwgJ29iaicsICdfJywgc291cmNlKTsKICAgIH0gY2F0Y2ggKGUpIHsKICAgICAgZS5zb3VyY2UgPSBzb3VyY2U7CiAgICAgIHRocm93IGU7CiAgICB9CgogICAgdmFyIHRlbXBsYXRlID0gZnVuY3Rpb24oZGF0YSkgewogICAgICByZXR1cm4gcmVuZGVyLmNhbGwodGhpcywgZGF0YSwgXyk7CiAgICB9OwoKICAgIC8vIFByb3ZpZGUgdGhlIGNvbXBpbGVkIHNvdXJjZSBhcyBhIGNvbnZlbmllbmNlIGZvciBwcmVjb21waWxhdGlvbi4KICAgIHZhciBhcmd1bWVudCA9IHNldHRpbmdzLnZhcmlhYmxlIHx8ICdvYmonOwogICAgdGVtcGxhdGUuc291cmNlID0gJ2Z1bmN0aW9uKCcgKyBhcmd1bWVudCArICcpe1xuJyArIHNvdXJjZSArICd9JzsKCiAgICByZXR1cm4gdGVtcGxhdGU7CiAgfTsKCiAgLy8gQWRkIGEgImNoYWluIiBmdW5jdGlvbi4gU3RhcnQgY2hhaW5pbmcgYSB3cmFwcGVkIFVuZGVyc2NvcmUgb2JqZWN0LgogIF8uY2hhaW4gPSBmdW5jdGlvbihvYmopIHsKICAgIHZhciBpbnN0YW5jZSA9IF8ob2JqKTsKICAgIGluc3RhbmNlLl9jaGFpbiA9IHRydWU7CiAgICByZXR1cm4gaW5zdGFuY2U7CiAgfTsKCiAgLy8gT09QCiAgLy8gLS0tLS0tLS0tLS0tLS0tCiAgLy8gSWYgVW5kZXJzY29yZSBpcyBjYWxsZWQgYXMgYSBmdW5jdGlvbiwgaXQgcmV0dXJucyBhIHdyYXBwZWQgb2JqZWN0IHRoYXQKICAvLyBjYW4gYmUgdXNlZCBPTy1zdHlsZS4gVGhpcyB3cmFwcGVyIGhvbGRzIGFsdGVyZWQgdmVyc2lvbnMgb2YgYWxsIHRoZQogIC8vIHVuZGVyc2NvcmUgZnVuY3Rpb25zLiBXcmFwcGVkIG9iamVjdHMgbWF5IGJlIGNoYWluZWQuCgogIC8vIEhlbHBlciBmdW5jdGlvbiB0byBjb250aW51ZSBjaGFpbmluZyBpbnRlcm1lZGlhdGUgcmVzdWx0cy4KICB2YXIgcmVzdWx0ID0gZnVuY3Rpb24oaW5zdGFuY2UsIG9iaikgewogICAgcmV0dXJuIGluc3RhbmNlLl9jaGFpbiA/IF8ob2JqKS5jaGFpbigpIDogb2JqOwogIH07CgogIC8vIEFkZCB5b3VyIG93biBjdXN0b20gZnVuY3Rpb25zIHRvIHRoZSBVbmRlcnNjb3JlIG9iamVjdC4KICBfLm1peGluID0gZnVuY3Rpb24ob2JqKSB7CiAgICBfLmVhY2goXy5mdW5jdGlvbnMob2JqKSwgZnVuY3Rpb24obmFtZSkgewogICAgICB2YXIgZnVuYyA9IF9bbmFtZV0gPSBvYmpbbmFtZV07CiAgICAgIF8ucHJvdG90eXBlW25hbWVdID0gZnVuY3Rpb24oKSB7CiAgICAgICAgdmFyIGFyZ3MgPSBbdGhpcy5fd3JhcHBlZF07CiAgICAgICAgcHVzaC5hcHBseShhcmdzLCBhcmd1bWVudHMpOwogICAgICAgIHJldHVybiByZXN1bHQodGhpcywgZnVuYy5hcHBseShfLCBhcmdzKSk7CiAgICAgIH07CiAgICB9KTsKICB9OwoKICAvLyBBZGQgYWxsIG9mIHRoZSBVbmRlcnNjb3JlIGZ1bmN0aW9ucyB0byB0aGUgd3JhcHBlciBvYmplY3QuCiAgXy5taXhpbihfKTsKCiAgLy8gQWRkIGFsbCBtdXRhdG9yIEFycmF5IGZ1bmN0aW9ucyB0byB0aGUgd3JhcHBlci4KICBfLmVhY2goWydwb3AnLCAncHVzaCcsICdyZXZlcnNlJywgJ3NoaWZ0JywgJ3NvcnQnLCAnc3BsaWNlJywgJ3Vuc2hpZnQnXSwgZnVuY3Rpb24obmFtZSkgewogICAgdmFyIG1ldGhvZCA9IEFycmF5UHJvdG9bbmFtZV07CiAgICBfLnByb3RvdHlwZVtuYW1lXSA9IGZ1bmN0aW9uKCkgewogICAgICB2YXIgb2JqID0gdGhpcy5fd3JhcHBlZDsKICAgICAgbWV0aG9kLmFwcGx5KG9iaiwgYXJndW1lbnRzKTsKICAgICAgaWYgKChuYW1lID09PSAnc2hpZnQnIHx8IG5hbWUgPT09ICdzcGxpY2UnKSAmJiBvYmoubGVuZ3RoID09PSAwKSBkZWxldGUgb2JqWzBdOwogICAgICByZXR1cm4gcmVzdWx0KHRoaXMsIG9iaik7CiAgICB9OwogIH0pOwoKICAvLyBBZGQgYWxsIGFjY2Vzc29yIEFycmF5IGZ1bmN0aW9ucyB0byB0aGUgd3JhcHBlci4KICBfLmVhY2goWydjb25jYXQnLCAnam9pbicsICdzbGljZSddLCBmdW5jdGlvbihuYW1lKSB7CiAgICB2YXIgbWV0aG9kID0gQXJyYXlQcm90b1tuYW1lXTsKICAgIF8ucHJvdG90eXBlW25hbWVdID0gZnVuY3Rpb24oKSB7CiAgICAgIHJldHVybiByZXN1bHQodGhpcywgbWV0aG9kLmFwcGx5KHRoaXMuX3dyYXBwZWQsIGFyZ3VtZW50cykpOwogICAgfTsKICB9KTsKCiAgLy8gRXh0cmFjdHMgdGhlIHJlc3VsdCBmcm9tIGEgd3JhcHBlZCBhbmQgY2hhaW5lZCBvYmplY3QuCiAgXy5wcm90b3R5cGUudmFsdWUgPSBmdW5jdGlvbigpIHsKICAgIHJldHVybiB0aGlzLl93cmFwcGVkOwogIH07CgogIC8vIFByb3ZpZGUgdW53cmFwcGluZyBwcm94eSBmb3Igc29tZSBtZXRob2RzIHVzZWQgaW4gZW5naW5lIG9wZXJhdGlvbnMKICAvLyBzdWNoIGFzIGFyaXRobWV0aWMgYW5kIEpTT04gc3RyaW5naWZpY2F0aW9uLgogIF8ucHJvdG90eXBlLnZhbHVlT2YgPSBfLnByb3RvdHlwZS50b0pTT04gPSBfLnByb3RvdHlwZS52YWx1ZTsKCiAgXy5wcm90b3R5cGUudG9TdHJpbmcgPSBmdW5jdGlvbigpIHsKICAgIHJldHVybiAnJyArIHRoaXMuX3dyYXBwZWQ7CiAgfTsKCiAgLy8gQU1EIHJlZ2lzdHJhdGlvbiBoYXBwZW5zIGF0IHRoZSBlbmQgZm9yIGNvbXBhdGliaWxpdHkgd2l0aCBBTUQgbG9hZGVycwogIC8vIHRoYXQgbWF5IG5vdCBlbmZvcmNlIG5leHQtdHVybiBzZW1hbnRpY3Mgb24gbW9kdWxlcy4gRXZlbiB0aG91Z2ggZ2VuZXJhbAogIC8vIHByYWN0aWNlIGZvciBBTUQgcmVnaXN0cmF0aW9uIGlzIHRvIGJlIGFub255bW91cywgdW5kZXJzY29yZSByZWdpc3RlcnMKICAvLyBhcyBhIG5hbWVkIG1vZHVsZSBiZWNhdXNlLCBsaWtlIGpRdWVyeSwgaXQgaXMgYSBiYXNlIGxpYnJhcnkgdGhhdCBpcwogIC8vIHBvcHVsYXIgZW5vdWdoIHRvIGJlIGJ1bmRsZWQgaW4gYSB0aGlyZCBwYXJ0eSBsaWIsIGJ1dCBub3QgYmUgcGFydCBvZgogIC8vIGFuIEFNRCBsb2FkIHJlcXVlc3QuIFRob3NlIGNhc2VzIGNvdWxkIGdlbmVyYXRlIGFuIGVycm9yIHdoZW4gYW4KICAvLyBhbm9ueW1vdXMgZGVmaW5lKCkgaXMgY2FsbGVkIG91dHNpZGUgb2YgYSBsb2FkZXIgcmVxdWVzdC4KICBpZiAodHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kKSB7CiAgICBkZWZpbmUoJ3VuZGVyc2NvcmUnLCBbXSwgZnVuY3Rpb24oKSB7CiAgICAgIHJldHVybiBfOwogICAgfSk7CiAgfQp9LmNhbGwodGhpcykpOwo="></script>
<script src="data:application/javascript;base64,Ly8gVmVuZG9yZWQgZnJvbSBodHRwczovL2dpdGh1Yi5jb20vcm1taC93ZWJ0cmVlbWFwL2Jsb2IvOWZhMGMwNjZhMTBlYTQ0MDJkOTYwYjBjNmMxYTQzMjg0NmFjN2ZjNC93ZWJ0cmVlbWFwLmpzCgovLyBDb3B5cmlnaHQgMjAxMyBHb29nbGUgSW5jLiBBbGwgUmlnaHRzIFJlc2VydmVkLgovLwovLyBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgIkxpY2Vuc2UiKTsKLy8geW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLgovLyBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXQKLy8KLy8gICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMAovLwovLyBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlCi8vIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuICJBUyBJUyIgQkFTSVMsCi8vIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLgovLyBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kCi8vIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLgoKLy8gU2l6ZSBvZiBib3JkZXIgYXJvdW5kIG5vZGVzLgovLyBXZSBjb3VsZCBzdXBwb3J0IGFyYml0cmFyeSBib3JkZXJzIHVzaW5nIGdldENvbXB1dGVkU3R5bGUoKSwgYnV0IEkgYW0KLy8gc2tlcHRpY2FsIHRoZSBleHRyYSBjb21wbGV4aXR5IChhbmQgcGVyZm9ybWFuY2UgaGl0KSBpcyB3b3J0aCBpdC4KCjsoZnVuY3Rpb24oKSB7CnZhciBrQm9yZGVyV2lkdGggPSAxOwoKLy8gUGFkZGluZyBhcm91bmQgY29udGVudHMuCi8vIFRPRE86IGRvIHRoaXMgd2l0aCBhIG5lc3RlZCBkaXYgdG8gYWxsb3cgaXQgdG8gYmUgQ1NTLXN0eWxlYWJsZS4KdmFyIGtQYWRkaW5nID0gNDsKCi8vIHgveSByYXRpbyB0byBhaW0gZm9yIC0tIHdpZGVyIHJlY3RhbmdsZXMgYXJlIGJldHRlciBmb3IgdGV4dCBkaXNwbGF5CnZhciBrQXNwZWN0UmF0aW8gPSAxLjI7Cgp2YXIgZm9jdXNlZCA9IG51bGw7CgpmdW5jdGlvbiBmb2N1cyh0cmVlKSB7CiAgZm9jdXNlZCA9IHRyZWU7CgogIC8vIEhpZGUgYWxsIHZpc2libGUgc2libGluZ3Mgb2YgYWxsIG91ciBhbmNlc3RvcnMgYnkgbG93ZXJpbmcgdGhlbS4KICB2YXIgbGV2ZWwgPSAwOwogIHZhciByb290ID0gdHJlZTsKICB3aGlsZSAocm9vdC5wYXJlbnQpIHsKICAgIHJvb3QgPSByb290LnBhcmVudDsKICAgIGxldmVsICs9IDE7CiAgICBmb3IgKHZhciBpID0gMCwgc2libGluZzsgc2libGluZyA9IHJvb3QuY2hpbGRyZW5baV07ICsraSkgewogICAgICBpZiAoc2libGluZy5kb20pCiAgICAgICAgc2libGluZy5kb20uc3R5bGUuekluZGV4ID0gMDsKICAgIH0KICB9CiAgdmFyIHdpZHRoID0gcm9vdC5kb20ub2Zmc2V0V2lkdGg7CiAgdmFyIGhlaWdodCA9IHJvb3QuZG9tLm9mZnNldEhlaWdodDsKICAvLyBVbmhpZGUgKHJhaXNlKSBhbmQgbWF4aW1pemUgdXMgYW5kIG91ciBhbmNlc3RvcnMuCiAgZm9yICh2YXIgdCA9IHRyZWU7IHQucGFyZW50OyB0ID0gdC5wYXJlbnQpIHsKICAgIC8vIFNoaWZ0IG9mZiBieSBib3JkZXIgc28gd2UgZG9uJ3QgZ2V0IG5lc3RlZCBib3JkZXJzLgogICAgLy8gVE9ETzogYWN0dWFsbHkgbWFrZSBuZXN0ZWQgYm9yZGVycyB3b3JrIChuZWVkIHRvIGFkanVzdCB3aWR0aC9oZWlnaHQpLgogICAgcG9zaXRpb24odC5kb20sIC1rQm9yZGVyV2lkdGgsIC1rQm9yZGVyV2lkdGgsIHdpZHRoLCBoZWlnaHQpOwogICAgdC5kb20uc3R5bGUuekluZGV4ID0gMTsKICB9CiAgLy8gQW5kIGxheW91dCBpbnRvIHRoZSB0b3Btb3N0IGJveC4KICBsYXlvdXQodHJlZSwgbGV2ZWwsIHdpZHRoLCBoZWlnaHQpOwp9CgpmdW5jdGlvbiBtYWtlRG9tKHRyZWUsIGxldmVsKSB7CiAgdmFyIGRvbSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpOwogIGRvbS5zdHlsZS56SW5kZXggPSAxOwogIGRvbS5jbGFzc05hbWUgPSAnd2VidHJlZW1hcC1ub2RlIHdlYnRyZWVtYXAtbGV2ZWwnICsgTWF0aC5taW4obGV2ZWwsIDQpOwogIGlmICh0cmVlLmRhdGFbJyRzeW1ib2wnXSkgewogICAgZG9tLmNsYXNzTmFtZSArPSAoJyB3ZWJ0cmVlbWFwLXN5bWJvbC0nICsKICB0cmVlLmRhdGFbJyRzeW1ib2wnXS5yZXBsYWNlKCcgJywgJ18nKSk7CiAgfQogIGlmICh0cmVlLmRhdGFbJyRkb21pbmFudF9zeW1ib2wnXSkgewogICAgZG9tLmNsYXNzTmFtZSArPSAoJyB3ZWJ0cmVlbWFwLXN5bWJvbC0nICsKICB0cmVlLmRhdGFbJyRkb21pbmFudF9zeW1ib2wnXS5yZXBsYWNlKCcgJywgJ18nKSk7CiAgICBkb20uY2xhc3NOYW1lICs9ICgnIHdlYnRyZWVtYXAtYWdncmVnYXRlJyk7CiAgfQoKICBkb20ub25tb3VzZWRvd24gPSBmdW5jdGlvbihlKSB7CiAgICBpZiAoZS5idXR0b24gPT0gMCkgewogICAgICBpZiAoZm9jdXNlZCAmJiB0cmVlID09IGZvY3VzZWQgJiYgZm9jdXNlZC5wYXJlbnQpIHsKICAgICAgICBmb2N1cyhmb2N1c2VkLnBhcmVudCk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgZm9jdXModHJlZSk7CiAgICAgIH0KICAgIH0KICAgIGUuc3RvcFByb3BhZ2F0aW9uKCk7CiAgICByZXR1cm4gdHJ1ZTsKICB9OwoKICB2YXIgY2FwdGlvbiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpOwogIGNhcHRpb24uY2xhc3NOYW1lID0gJ3dlYnRyZWVtYXAtY2FwdGlvbic7CiAgY2FwdGlvbi5pbm5lckhUTUwgPSB0cmVlLm5hbWU7CiAgZG9tLmFwcGVuZENoaWxkKGNhcHRpb24pOwogIGRvbS50aXRsZSA9IHRyZWUubmFtZTsKCiAgdHJlZS5kb20gPSBkb207CiAgcmV0dXJuIGRvbTsKfQoKZnVuY3Rpb24gcG9zaXRpb24oZG9tLCB4LCB5LCB3aWR0aCwgaGVpZ2h0KSB7CiAgLy8gQ1NTIHdpZHRoL2hlaWdodCBkb2VzIG5vdCBpbmNsdWRlIGJvcmRlci4KICB3aWR0aCAtPSBrQm9yZGVyV2lkdGgqMjsKICBoZWlnaHQgLT0ga0JvcmRlcldpZHRoKjI7CgogIGRvbS5zdHlsZS5sZWZ0ICAgPSB4ICsgJ3B4JzsKICBkb20uc3R5bGUudG9wICAgID0geSArICdweCc7CiAgZG9tLnN0eWxlLndpZHRoICA9IE1hdGgubWF4KHdpZHRoLCAwKSArICdweCc7CiAgZG9tLnN0eWxlLmhlaWdodCA9IE1hdGgubWF4KGhlaWdodCwgMCkgKyAncHgnOwp9CgovLyBHaXZlbiBhIGxpc3Qgb2YgcmVjdGFuZ2xlcyB8bm9kZXN8LCB0aGUgMS1kIHNwYWNlIGF2YWlsYWJsZQovLyB8c3BhY2V8LCBhbmQgYSBzdGFydGluZyByZWN0YW5nbGUgaW5kZXggfHN0YXJ0fCwgY29tcHV0ZSBhbiBzcGFuIG9mCi8vIHJlY3RhbmdsZXMgdGhhdCBvcHRpbWl6ZXMgYSBwbGVhc2FudCBhc3BlY3QgcmF0aW8uCi8vCi8vIFJldHVybnMgW2VuZCwgc3VtXSwgd2hlcmUgZW5kIGlzIG9uZSBwYXN0IHRoZSBsYXN0IHJlY3RhbmdsZSBhbmQgc3VtIGlzIHRoZQovLyAyLWQgc3VtIG9mIHRoZSByZWN0YW5nbGVzJyBhcmVhcy4KZnVuY3Rpb24gc2VsZWN0U3Bhbihub2Rlcywgc3BhY2UsIHN0YXJ0KSB7CiAgLy8gQWRkIHJlY3RhbmdsZSBvbmUgYnkgb25lLCBzdG9wcGluZyB3aGVuIGFzcGVjdCByYXRpb3MgYmVnaW4gdG8gZ28KICAvLyBiYWQuICBSZXN1bHQgaXMgW3N0YXJ0LGVuZCkgY292ZXJpbmcgdGhlIGJlc3QgcnVuIGZvciB0aGlzIHNwYW4uCiAgLy8gaHR0cDovL2NpdGVzZWVyeC5pc3QucHN1LmVkdS92aWV3ZG9jL3N1bW1hcnk/ZG9pPTEwLjEuMS4zNi42Njg1CiAgdmFyIG5vZGUgPSBub2Rlc1tzdGFydF07CiAgdmFyIHJtaW4gPSBub2RlLmRhdGFbJyRhcmVhJ107ICAvLyBTbWFsbGVzdCBzZWVuIGNoaWxkIHNvIGZhci4KICB2YXIgcm1heCA9IHJtaW47ICAgICAgICAgICAgICAgIC8vIExhcmdlc3QgY2hpbGQuCiAgdmFyIHJzdW0gPSAwOyAgICAgICAgICAgICAgICAgICAvLyBTdW0gb2YgY2hpbGRyZW4gaW4gdGhpcyBzcGFuLgogIHZhciBsYXN0X3Njb3JlID0gMDsgICAgICAgICAgICAgLy8gQmVzdCBzY29yZSB5ZXQgZm91bmQuCiAgZm9yICh2YXIgZW5kID0gc3RhcnQ7IG5vZGUgPSBub2Rlc1tlbmRdOyArK2VuZCkgewogICAgdmFyIHNpemUgPSBub2RlLmRhdGFbJyRhcmVhJ107CiAgICBpZiAoc2l6ZSA8IHJtaW4pCiAgICAgIHJtaW4gPSBzaXplOwogICAgaWYgKHNpemUgPiBybWF4KQogICAgICBybWF4ID0gc2l6ZTsKICAgIHJzdW0gKz0gc2l6ZTsKCiAgICAvLyBUaGlzIGZvcm11bGEgaXMgZnJvbSB0aGUgcGFwZXIsIGJ1dCB5b3UgY2FuIGVhc2lseSBwcm92ZSB0bwogICAgLy8geW91cnNlbGYgaXQncyB0YWtpbmcgdGhlIGxhcmdlciBvZiB0aGUgeC95IGFzcGVjdCByYXRpbyBvciB0aGUKICAgIC8vIHkveCBhc3BlY3QgcmF0aW8uICBUaGUgYWRkaXRpb25hbCBtYWdpYyBmdWRnZSBjb25zdGFudCBvZiBrQXNwZWN0UmF0aW8KICAgIC8vIGxldHMgdXMgcHJlZmVyIHdpZGVyIHJlY3RhbmdsZXMgdG8gdGFsbGVyIG9uZXMuCiAgICB2YXIgc2NvcmUgPSBNYXRoLm1heChzcGFjZSpzcGFjZSpybWF4IC8gKHJzdW0qcnN1bSksCiAgICAgICAgICAgICAgICAgICAgICAgICBrQXNwZWN0UmF0aW8qcnN1bSpyc3VtIC8gKHNwYWNlKnNwYWNlKnJtaW4pKTsKICAgIGlmIChsYXN0X3Njb3JlICYmIHNjb3JlID4gbGFzdF9zY29yZSkgewogICAgICByc3VtIC09IHNpemU7ICAvLyBVbmRvIHNpemUgYWRkaXRpb24gZnJvbSBqdXN0IGFib3ZlLgogICAgICBicmVhazsKICAgIH0KICAgIGxhc3Rfc2NvcmUgPSBzY29yZTsKICB9CiAgcmV0dXJuIFtlbmQsIHJzdW1dOwp9CgpmdW5jdGlvbiBsYXlvdXQodHJlZSwgbGV2ZWwsIHdpZHRoLCBoZWlnaHQpIHsKICBpZiAoISgnY2hpbGRyZW4nIGluIHRyZWUpKQogICAgcmV0dXJuOwoKICB2YXIgdG90YWwgPSB0cmVlLmRhdGFbJyRhcmVhJ107CgogIC8vIFhYWCB3aHkgZG8gSSBuZWVkIGFuIGV4dHJhIC0xLy0yIGhlcmUgZm9yIHdpZHRoL2hlaWdodCB0byBsb29rIHJpZ2h0PwogIHZhciB4MSA9IDAsIHkxID0gMCwgeDIgPSB3aWR0aCAtIDEsIHkyID0gaGVpZ2h0IC0gMjsKICB4MSArPSBrUGFkZGluZzsgeTEgKz0ga1BhZGRpbmc7CiAgeDIgLT0ga1BhZGRpbmc7IHkyIC09IGtQYWRkaW5nOwogIHkxICs9IDE0OyAgLy8gWFhYIGdldCBmaXJzdCBjaGlsZCBoZWlnaHQgZm9yIGNhcHRpb24gc3BhY2luZwoKICB2YXIgcGl4ZWxzX3RvX3VuaXRzID0gTWF0aC5zcXJ0KHRvdGFsIC8gKCh4MiAtIHgxKSAqICh5MiAtIHkxKSkpOwoKICAvLyBUaGUgYWxnb3JpdGhtIGRvZXMgYmVzdCBhdCBsYXlpbmcgb3V0IGl0ZW1zIGZyb20gbGFyZ2VzdCB0byBzbWFsbGVzdC4KICAvLyBTb3J0IHRoZW0gdG8gZW5zdXJlIHRoaXMuCiAgaWYgKCF0cmVlLmNoaWxkcmVuLnNvcnRlZCkgewogICAgdHJlZS5jaGlsZHJlbi5zb3J0KGZ1bmN0aW9uIChhLCBiKSB7CiAgICAgIHJldHVybiBiLmRhdGFbJyRhcmVhJ10gLSBhLmRhdGFbJyRhcmVhJ107CiAgICB9KTsKICAgIHRyZWUuY2hpbGRyZW4uc29ydGVkID0gdHJ1ZTsKICB9CgogIGZvciAodmFyIHN0YXJ0ID0gMCwgY2hpbGQ7IGNoaWxkID0gdHJlZS5jaGlsZHJlbltzdGFydF07ICsrc3RhcnQpIHsKICAgIGlmICh4MiAtIHgxIDwgNjAgfHwgeTIgLSB5MSA8IDQwKSB7CiAgICAgIGlmIChjaGlsZC5kb20pIHsKICAgICAgICBjaGlsZC5kb20uc3R5bGUuekluZGV4ID0gMDsKICAgICAgICBwb3NpdGlvbihjaGlsZC5kb20sIC0yLCAtMiwgMCwgMCk7CiAgICAgIH0KICAgICAgY29udGludWU7CiAgICB9CgogICAgLy8gRHluYW1pY2FsbHkgZGVjaWRlIHdoZXRoZXIgdG8gc3BsaXQgaW4geCBvciB5IGJhc2VkIG9uIGFzcGVjdCByYXRpby4KICAgIHZhciB5c3BsaXQgPSAoKHkyIC0geTEpIC8gKHgyIC0geDEpKSA+IGtBc3BlY3RSYXRpbzsKCiAgICB2YXIgc3BhY2U7ICAvLyBTcGFjZSBhdmFpbGFibGUgYWxvbmcgbGF5b3V0IGF4aXMuCiAgICBpZiAoeXNwbGl0KQogICAgICBzcGFjZSA9ICh5MiAtIHkxKSAqIHBpeGVsc190b191bml0czsKICAgIGVsc2UKICAgICAgc3BhY2UgPSAoeDIgLSB4MSkgKiBwaXhlbHNfdG9fdW5pdHM7CgogICAgdmFyIHNwYW4gPSBzZWxlY3RTcGFuKHRyZWUuY2hpbGRyZW4sIHNwYWNlLCBzdGFydCk7CiAgICB2YXIgZW5kID0gc3BhblswXSwgcnN1bSA9IHNwYW5bMV07CgogICAgLy8gTm93IHRoYXQgd2UndmUgc2VsZWN0ZWQgYSBzcGFuLCBsYXkgb3V0IHJlY3RhbmdsZXMgW3N0YXJ0LGVuZCkgaW4gb3VyCiAgICAvLyBhdmFpbGFibGUgc3BhY2UuCiAgICB2YXIgeCA9IHgxLCB5ID0geTE7CiAgICBmb3IgKHZhciBpID0gc3RhcnQ7IGkgPCBlbmQ7ICsraSkgewogICAgICBjaGlsZCA9IHRyZWUuY2hpbGRyZW5baV07CiAgICAgIGlmICghY2hpbGQuZG9tKSB7CiAgICAgICAgY2hpbGQucGFyZW50ID0gdHJlZTsKICAgICAgICBjaGlsZC5kb20gPSBtYWtlRG9tKGNoaWxkLCBsZXZlbCArIDEpOwogICAgICAgIHRyZWUuZG9tLmFwcGVuZENoaWxkKGNoaWxkLmRvbSk7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgY2hpbGQuZG9tLnN0eWxlLnpJbmRleCA9IDE7CiAgICAgIH0KICAgICAgdmFyIHNpemUgPSBjaGlsZC5kYXRhWyckYXJlYSddOwogICAgICB2YXIgZnJhYyA9IHNpemUgLyByc3VtOwogICAgICBpZiAoeXNwbGl0KSB7CiAgICAgICAgd2lkdGggPSByc3VtIC8gc3BhY2U7CiAgICAgICAgaGVpZ2h0ID0gc2l6ZSAvIHdpZHRoOwogICAgICB9IGVsc2UgewogICAgICAgIGhlaWdodCA9IHJzdW0gLyBzcGFjZTsKICAgICAgICB3aWR0aCA9IHNpemUgLyBoZWlnaHQ7CiAgICAgIH0KICAgICAgd2lkdGggLz0gcGl4ZWxzX3RvX3VuaXRzOwogICAgICBoZWlnaHQgLz0gcGl4ZWxzX3RvX3VuaXRzOwogICAgICB3aWR0aCA9IE1hdGgucm91bmQod2lkdGgpOwogICAgICBoZWlnaHQgPSBNYXRoLnJvdW5kKGhlaWdodCk7CiAgICAgIHBvc2l0aW9uKGNoaWxkLmRvbSwgeCwgeSwgd2lkdGgsIGhlaWdodCk7CiAgICAgIGlmICgnY2hpbGRyZW4nIGluIGNoaWxkKSB7CiAgICAgICAgbGF5b3V0KGNoaWxkLCBsZXZlbCArIDEsIHdpZHRoLCBoZWlnaHQpOwogICAgICB9CiAgICAgIGlmICh5c3BsaXQpCiAgICAgICAgeSArPSBoZWlnaHQ7CiAgICAgIGVsc2UKICAgICAgICB4ICs9IHdpZHRoOwogICAgfQoKICAgIC8vIFNocmluayBvdXIgYXZhaWxhYmxlIHNwYWNlIGJhc2VkIG9uIHRoZSBhbW91bnQgd2UgdXNlZC4KICAgIGlmICh5c3BsaXQpCiAgICAgIHgxICs9IE1hdGgucm91bmQoKHJzdW0gLyBzcGFjZSkgLyBwaXhlbHNfdG9fdW5pdHMpOwogICAgZWxzZQogICAgICB5MSArPSBNYXRoLnJvdW5kKChyc3VtIC8gc3BhY2UpIC8gcGl4ZWxzX3RvX3VuaXRzKTsKCiAgICAvLyBlbmQgcG9pbnRzIG9uZSBwYXN0IHdoZXJlIHdlIGVuZGVkLCB3aGljaCBpcyB3aGVyZSB3ZSB3YW50IHRvCiAgICAvLyBiZWdpbiB0aGUgbmV4dCBpdGVyYXRpb24sIGJ1dCBzdWJ0cmFjdCBvbmUgdG8gYmFsYW5jZSB0aGUgKysgaW4KICAgIC8vIHRoZSBsb29wLgogICAgc3RhcnQgPSBlbmQgLSAxOwogIH0KfQoKZnVuY3Rpb24gYXBwZW5kVHJlZW1hcChkb20sIGRhdGEpIHsKICB2YXIgc3R5bGUgPSBnZXRDb21wdXRlZFN0eWxlKGRvbSwgbnVsbCk7CiAgdmFyIHdpZHRoID0gcGFyc2VJbnQoc3R5bGUud2lkdGgpOwogIHZhciBoZWlnaHQgPSBwYXJzZUludChzdHlsZS5oZWlnaHQpOwogIGlmICghZGF0YS5kb20pCiAgICBtYWtlRG9tKGRhdGEsIDApOwogIGRvbS5hcHBlbmRDaGlsZChkYXRhLmRvbSk7CiAgcG9zaXRpb24oZGF0YS5kb20sIDAsIDAsIHdpZHRoLCBoZWlnaHQpOwogIGxheW91dChkYXRhLCAwLCB3aWR0aCwgaGVpZ2h0KTsKfQoKd2luZG93LmFwcGVuZFRyZWVtYXAgPSBhcHBlbmRUcmVlbWFwOwp9KSh3aW5kb3cpOwo="></script>
<script>
function newNode(name) {
return {
name: name,
data: {
'$area': 0
},
children: []
};
}
var treeData = newNode('/');
function addNode(path, size) {
var parts = path.split('/');
var node = treeData;
node.data['$area'] += size;
parts.forEach(function(part) {
var child = _.find(node.children, function(child) { return child.name == part; });
if (!child) {
var child = newNode(part);
node.children.push(child);
}
node = child;
node.data['$area'] += size;
});
}
function addSizeToTitle(node, total) {
var size = node.data['$area'],
pct = 100.0 * size / total;
node.name += ' • ' + formatBytes(size) + ' • ' + pct.toFixed(1) + '%';
node.children.forEach(function(x) { addSizeToTitle(x, total) });
}
for (var source in tree) {
addNode(source, tree[source]);
}
addSizeToTitle(treeData, treeData.data['$area']);
var map = document.getElementById('map');
appendTreemap(map, treeData);
window.addEventListener('resize', function() {
appendTreemap(map, treeData);
});
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment