cGFja2FnZSBldmVudAoKaW1wb3J0ICgKCSJjb250ZXh0IgoJInN0cmluZ3MiCgkidGltZSIKCgkiZ2l0aHViLmNvbS9ycy96ZXJvbG9nIgoKCSJnaXRodWIuY29tL3ZpbmNlbnRjLWFmay9naXRlYS1ub3RpZmljYXRpb24taHViL2ludGVybmFsL2NvbmZpZyIKCSJnaXRodWIuY29tL3ZpbmNlbnRjLWFmay9naXRlYS1ub3RpZmljYXRpb24taHViL2ludGVybmFsL3dlYmhvb2siCikKCi8vIElkZW50aXR5UmVzb2x2ZXIgcmVzb2x2ZXMgR2l0ZWEgdXNlcnMgdG8gZXh0ZXJuYWwgaWRlbnRpdGllcyAoZS5nLiwgU2xhY2spCnR5cGUgSWRlbnRpdHlSZXNvbHZlciBpbnRlcmZhY2UgewoJUmVzb2x2ZShjdHggY29udGV4dC5Db250ZXh0LCB1c2VyIFVzZXIpICgqUmVzb2x2ZWRJZGVudGl0eSwgZXJyb3IpCn0KCi8vIFJlc29sdmVkSWRlbnRpdHkgcmVwcmVzZW50cyBhIHJlc29sdmVkIGV4dGVybmFsIGlkZW50aXR5CnR5cGUgUmVzb2x2ZWRJZGVudGl0eSBzdHJ1Y3QgewoJRW1haWwgICAgc3RyaW5nIGBqc29uOiJlbWFpbCJgCglTbGFja0lEICBzdHJpbmcgYGpzb246InNsYWNrX2lkImAKCVNsYWNrTmFtZSBzdHJpbmcgYGpzb246InNsYWNrX25hbWUiYAp9CgovLyBOb3RpZmllciBzZW5kcyBub3RpZmljYXRpb25zCnR5cGUgTm90aWZpZXIgaW50ZXJmYWNlIHsKCVNlbmREaXJlY3QoY3R4IGNvbnRleHQuQ29udGV4dCwgdXNlcklEIHN0cmluZywgbXNnICpOb3RpZmljYXRpb24pIGVycm9yCglTZW5kQ2hhbm5lbChjdHggY29udGV4dC5Db250ZXh0LCBjaGFubmVsIHN0cmluZywgbXNnICpOb3RpZmljYXRpb24pIGVycm9yCn0KCi8vIFByb2Nlc3NvciBwcm9jZXNzZXMgd2ViaG9vayBldmVudHMgYW5kIGdlbmVyYXRlcyBub3RpZmljYXRpb25zCnR5cGUgUHJvY2Vzc29yIHN0cnVjdCB7CgljZmcgICAgICAqY29uZmlnLkNvbmZpZwoJcmVzb2x2ZXIgSWRlbnRpdHlSZXNvbHZlcgoJbm90aWZpZXIgTm90aWZpZXIKCWxvZ2dlciAgIHplcm9sb2cuTG9nZ2VyCn0KCi8vIE5ld1Byb2Nlc3NvciBjcmVhdGVzIGEgbmV3IGV2ZW50IHByb2Nlc3NvcgpmdW5jIE5ld1Byb2Nlc3NvcihjZmcgKmNvbmZpZy5Db25maWcsIHJlc29sdmVyIElkZW50aXR5UmVzb2x2ZXIsIG5vdGlmaWVyIE5vdGlmaWVyLCBsb2dnZXIgemVyb2xvZy5Mb2dnZXIpICpQcm9jZXNzb3IgewoJcmV0dXJuICZQcm9jZXNzb3J7CgkJY2ZnOiAgICAgIGNmZywKCQlyZXNvbHZlcjogcmVzb2x2ZXIsCgkJbm90aWZpZXI6IG5vdGlmaWVyLAoJCWxvZ2dlcjogICBsb2dnZXIuV2l0aCgpLlN0cigiY29tcG9uZW50IiwgInByb2Nlc3NvciIpLkxvZ2dlcigpLAoJfQp9CgovLyBIYW5kbGVQdWxsUmVxdWVzdCBwcm9jZXNzZXMgcHVsbCByZXF1ZXN0IGV2ZW50cwpmdW5jIChwICpQcm9jZXNzb3IpIEhhbmRsZVB1bGxSZXF1ZXN0KGUgKndlYmhvb2suUHVsbFJlcXVlc3RFdmVudCkgewoJY3R4IDo9IGNvbnRleHQuQmFja2dyb3VuZCgpCglldmVudCA6PSBwLm5vcm1hbGl6ZVBSRXZlbnQoZSkKCglwLmxvZ2dlci5EZWJ1ZygpLgoJCVN0cigiYWN0aW9uIiwgZS5BY3Rpb24pLgoJCUludCgiYXNzaWduZWVzX2NvdW50IiwgbGVuKGV2ZW50LkFzc2lnbmVlcykpLgoJCUludCgicmV2aWV3ZXJzX2NvdW50IiwgbGVuKGV2ZW50LlJldmlld2VycykpLgoJCVN0cigiYWN0b3IiLCBldmVudC5BY3Rvci5HaXRlYVVzZXJuYW1lKS4KCQlNc2coInByb2Nlc3NpbmcgUFIgZXZlbnQiKQoKCXZhciB1c2Vyc1RvTm90aWZ5IFtdc3RydWN0IHsKCQl1c2VyICAgVXNlcgoJCXJlYXNvbiBOb3RpZmljYXRpb25SZWFzb24KCX0KCglzd2l0Y2ggZS5BY3Rpb24gewoJY2FzZSAib3BlbmVkIjoKCQlldmVudC5UeXBlID0gVHlwZVBST3BlbmVkCgkJLy8gTm90aWZ5IGFzc2lnbmVlcyBhbmQgcmV2aWV3ZXJzCgkJaWYgcC5jZmcuUnVsZXMuUFIuTm90aWZ5QXNzaWduZWVzIHsKCQkJZm9yIF8sIHUgOj0gcmFuZ2UgZXZlbnQuQXNzaWduZWVzIHsKCQkJCXAubG9nZ2VyLkRlYnVnKCkuU3RyKCJhc3NpZ25lZSIsIHUuR2l0ZWFVc2VybmFtZSkuTXNnKCJhZGRpbmcgYXNzaWduZWUgdG8gbm90aWZ5IikKCQkJCXVzZXJzVG9Ob3RpZnkgPSBhcHBlbmQodXNlcnNUb05vdGlmeSwgc3RydWN0IHsKCQkJCQl1c2VyICAgVXNlcgoJCQkJCXJlYXNvbiBOb3RpZmljYXRpb25SZWFzb24KCQkJCX17dSwgUmVhc29uQXNzaWduZWV9KQoJCQl9CgkJfQoJCWlmIHAuY2ZnLlJ1bGVzLlBSLk5vdGlmeVJldmlld2VycyB7CgkJCWZvciBfLCB1IDo9IHJhbmdlIGV2ZW50LlJldmlld2VycyB7CgkJCQlwLmxvZ2dlci5EZWJ1ZygpLlN0cigicmV2aWV3ZXIiLCB1LkdpdGVhVXNlcm5hbWUpLk1zZygiYWRkaW5nIHJldmlld2VyIHRvIG5vdGlmeSIpCgkJCQl1c2Vyc1RvTm90aWZ5ID0gYXBwZW5kKHVzZXJzVG9Ob3RpZnksIHN0cnVjdCB7CgkJCQkJdXNlciAgIFVzZXIKCQkJCQlyZWFzb24gTm90aWZpY2F0aW9uUmVhc29uCgkJCQl9e3UsIFJlYXNvblJldmlld2VyfSkKCQkJfQoJCX0KCgljYXNlICJjbG9zZWQiOgoJCWlmIGUuUHVsbFJlcXVlc3QuTWVyZ2VkIHsKCQkJZXZlbnQuVHlwZSA9IFR5cGVQUk1lcmdlZAoJCX0gZWxzZSB7CgkJCWV2ZW50LlR5cGUgPSBUeXBlUFJDbG9zZWQKCQl9CgkJLy8gTm90aWZ5IG93bmVyCgkJaWYgcC5jZmcuUnVsZXMuUFIuTm90aWZ5T3duZXIgJiYgZXZlbnQuT3duZXIgIT0gbmlsIHsKCQkJdXNlcnNUb05vdGlmeSA9IGFwcGVuZCh1c2Vyc1RvTm90aWZ5LCBzdHJ1Y3QgewoJCQkJdXNlciAgIFVzZXIKCQkJCXJlYXNvbiBOb3RpZmljYXRpb25SZWFzb24KCQkJfXsqZXZlbnQuT3duZXIsIFJlYXNvbk93bmVyfSkKCQl9CgoJY2FzZSAiYXNzaWduZWQiOgoJCWV2ZW50LlR5cGUgPSBUeXBlUFJBc3NpZ25lZAoJCS8vIE5vdGlmeSBuZXdseSBhc3NpZ25lZCB1c2VyCgkJaWYgZS5Bc3NpZ25lZSAhPSBuaWwgJiYgcC5jZmcuUnVsZXMuUFIuTm90aWZ5QXNzaWduZWVzIHsKCQkJcC5sb2dnZXIuRGVidWcoKS5TdHIoImFzc2lnbmVlIiwgZS5Bc3NpZ25lZS5Mb2dpbikuTXNnKCJhZGRpbmcgbmV3bHkgYXNzaWduZWQgdXNlciB0byBub3RpZnkiKQoJCQl1c2Vyc1RvTm90aWZ5ID0gYXBwZW5kKHVzZXJzVG9Ob3RpZnksIHN0cnVjdCB7CgkJCQl1c2VyICAgVXNlcgoJCQkJcmVhc29uIE5vdGlmaWNhdGlvblJlYXNvbgoJCQl9e2dpdGVhVXNlclRvVXNlcigqZS5Bc3NpZ25lZSksIFJlYXNvbkFzc2lnbmVlfSkKCQl9CgoJY2FzZSAicmV2aWV3X3JlcXVlc3RlZCI6CgkJZXZlbnQuVHlwZSA9IFR5cGVQUlJldmlld1JlcXVlc3RlZAoJCS8vIE5vdGlmeSBuZXdseSByZXF1ZXN0ZWQgcmV2aWV3ZXJzCgkJLy8gR2l0ZWEgbWF5IHNlbmQgcmVxdWVzdGVkX3Jldmlld2VycyAoYXJyYXkpIE9SIHJlcXVlc3RlZF9yZXZpZXdlciAoc2luZ3VsYXIpCgkJaWYgbGVuKGUuUmVxdWVzdGVkUmV2aWV3ZXJzKSA+IDAgewoJCQlwLmxvZ2dlci5JbmZvKCkuSW50KCJjb3VudCIsIGxlbihlLlJlcXVlc3RlZFJldmlld2VycykpLk1zZygicmV2aWV3X3JlcXVlc3RlZCB3aXRoIFJlcXVlc3RlZFJldmlld2VycyBhcnJheSIpCgkJCWZvciBfLCByZXZpZXdlciA6PSByYW5nZSBlLlJlcXVlc3RlZFJldmlld2VycyB7CgkJCQl1c2Vyc1RvTm90aWZ5ID0gYXBwZW5kKHVzZXJzVG9Ob3RpZnksIHN0cnVjdCB7CgkJCQkJdXNlciAgIFVzZXIKCQkJCQlyZWFzb24gTm90aWZpY2F0aW9uUmVhc29uCgkJCQl9e2dpdGVhVXNlclRvVXNlcihyZXZpZXdlciksIFJlYXNvblJldmlld2VyfSkKCQkJfQoJCX0gZWxzZSBpZiBlLlJlcXVlc3RlZFJldmlld2VyICE9IG5pbCB7CgkJCXAubG9nZ2VyLkluZm8oKS4KCQkJCVN0cigicmVxdWVzdGVkX3Jldmlld2VyIiwgZS5SZXF1ZXN0ZWRSZXZpZXdlci5Mb2dpbikuCgkJCQlNc2coInJldmlld19yZXF1ZXN0ZWQgd2l0aCBSZXF1ZXN0ZWRSZXZpZXdlciAoc2luZ3VsYXIpIikKCQkJdXNlcnNUb05vdGlmeSA9IGFwcGVuZCh1c2Vyc1RvTm90aWZ5LCBzdHJ1Y3QgewoJCQkJdXNlciAgIFVzZXIKCQkJCXJlYXNvbiBOb3RpZmljYXRpb25SZWFzb24KCQkJfXtnb2l0ZWFVc2VyVG9Vc2VyKCplLlJlcXVlc3RlZFJldmlld2VyKSwgUmVhc29uUmV2aWV3ZXJ9KQoJCX0gZWxzZSB7CgkJCXAubG9nZ2VyLkluZm8oKS5Nc2coInJldmlld19yZXF1ZXN0ZWQgYnV0IG5vIHJldmlld2VyIGRhdGEgZm91bmQiKQoJCX0KCWNhc2UgInN5bmNocm9uaXplIjoKCQlldmVudC5UeXBlID0gVHlwZVBSU3luY2hyb25pemVkCgkJLy8gQWRkIGNvbW1pdHMgaW5mbyB0byBldmVudAoJCWV2ZW50LkNvbW1pdHMgPSBtYWtlKFtdQ29tbWl0SW5mbywgMCwgbGVuKGUuQ29tbWl0cykpCgkJZm9yIF8sIGMgOj0gcmFuZ2UgZS5Db21taXRzIHsKCQkJLy8gR2V0IGZpcnN0IGxpbmUgb2YgY29tbWl0IG1lc3NhZ2UKCQkJbXNnIDo9IGMuTWVzc2FnZQoJCQlpZiBpZHggOj0gc3RyaW5ncy5JbmRleChtc2csICJcbiIpOyBpZHggPiAwIHsKCQkJCW1zZyA9IG1zZ1s6aWR4XQoJCQl9CgkJCWV2ZW50LkNvbW1pdHMgPSBhcHBlbmQoZXZlbnQuQ29tbWl0cywgQ29tbWl0SW5mb3sKCQkJCVNIQTogICAgIGMuSURbOjddLCAvLyBTaG9ydCBTSEEKCQkJCU1lc3NhZ2U6IG1zZywKCQkJCVVSTDogICAgIGMuVVJMLAoJCQkJQXV0aG9yOiAgYy5BdXRob3IuTmFtZSwKCQkJfSkKCQl9CgkJLy8gTm90aWZ5IG93bmVyICh3aWxsIGJlIGZpbHRlcmVkIG91dCBpZiB0aGV5IHB1c2hlZCB0aGUgY29tbWl0cykKCQlpZiBwLmNmZy5SdWxlcy5QUi5Ob3RpZnlPd25lciAmJiBldmVudC5Pd25lciAhPSBuaWwgewoJCQl1c2Vyc1RvTm90aWZ5ID0gYXBwZW5kKHVzZXJzVG9Ob3RpZnksIHN0cnVjdCB7CgkJCQl1c2VyICAgVXNlcgoJCQkJcmVhc29uIE5vdGlmaWNhdGlvblJlYXNvbgoJCQl9eypldmVudC5Pd25lciwgUmVhc29uT3duZXJ9KQoJCX0KCQkvLyBOb3RpZnkgcmV2aWV3ZXJzCgkJaWYgcC5jZmcuUnVsZXMuUFIuTm90aWZ5UmV2aWV3ZXJzIHsKCQkJZm9yIF8sIHUgOj0gcmFuZ2UgZXZlbnQuUmV2aWV3ZXJzIHsKCQkJCXVzZXJzVG9Ob3RpZnkgPSBhcHBlbmQodXNlcnNUb05vdGlmeSwgc3RydWN0IHsKCQkJCQl1c2VyICAgVXNlcgoJCQkJCXJlYXNvbiBOb3RpZmljYXRpb25SZWFzb24KCQkJCX17dSwgUmVhc29uUmV2aWV3ZXJ9KQoJCQl9CgkJfQoJCS8vIE5vdGlmeSBhc3NpZ25lZXMKCQlpZiBwLmNmZy5SdWxlcy5QUi5Ob3RpZnlBc3NpZ25lZXMgewoJCQlmb3IgXywgdSA6PSByYW5nZSBldmVudC5Bc3NpZ25lZXMgewoJCQkJdXNlcnNUb05vdGlmeSA9IGFwcGVuZCh1c2Vyc1RvTm90aWZ5LCBzdHJ1Y3QgewoJCQkJCXVzZXIgICBVc2VyCgkJCQkJcmVhc29uIE5vdGlmaWNhdGlvblJlYXNvbgoJCQkJfXt1LCBSZWFzb25Bc3NpZ25lZX0pCgkJCX0KCQl9Cgl9CgoJLy8gUmVtb3ZlIHRoZSBhY3RvciBmcm9tIG5vdGlmaWNhdGlvbnMgKGRvbid0IG5vdGlmeSB5b3Vyc2VsZikKCWJlZm9yZUZpbHRlciA6PSBsZW4odXNlcnNUb05vdGlmeSkKCXVzZXJzVG9Ob3RpZnkgPSBwLmZpbHRlck91dEFjdG9yKHVzZXJzVG9Ob3RpZnksIGV2ZW50LkFjdG9yKQoJcC5sb2dnZXIuRGVidWcoKS4KCQlJbnQoImJlZm9yZV9maWx0ZXIiLCBiZWZvcmVGaWx0ZXIpLgoJCUludCgiYWZ0ZXJfZmlsdGVyIiwgbGVuKHVzZXJzVG9Ob3RpZnkpKS4KCQlTdHIoImFjdG9yX2ZpbHRlcmVkIiwgZXZlbnQuQWN0b3IuR2l0ZWFVc2VybmFtZSkuCgkJTXNnKCJmaWx0ZXJlZCBvdXQgYWN0b3IgZnJvbSBub3RpZmljYXRpb25zIikKCgkvLyBTZW5kIG5vdGlmaWNhdGlvbnMKCXAuc2VuZE5vdGlmaWNhdGlvbnMoY3R4LCBldmVudCwgdXNlcnNUb05vdGlmeSkKfQoKLy8gSGFuZGxlUHVsbFJlcXVlc3RSZXZpZXcgcHJvY2Vzc2VzIFBSIHJldmlldyBldmVudHMKZnVuYyAocCAqUHJvY2Vzc29yKSBIYW5kbGVQdWxsUmVxdWVzdFJldmlldyhlICp3ZWJob29rLlB1bGxSZXF1ZXN0UmV2aWV3RXZlbnQpIHsKCWN0eCA6PSBjb250ZXh0LkJhY2tncm91bmQoKQoJZXZlbnQgOj0gcC5ub3JtYWxpemVSZXZpZXdFdmVudChlKQoKCXZhciB1c2Vyc1RvTm90aWZ5IFtdc3RydWN0IHsKCQl1c2VyICAgVXNlcgoJCXJlYXNvbiBOb3RpZmljYXRpb25SZWFzb24KCX0KCgkvLyBOb3RpZnkgUFIgb3duZXIgYWJvdXQgdGhlIHJldmlldwoJaWYgcC5jZmcuUnVsZXMuUFIuTm90aWZ5T3duZXIgJiYgZXZlbnQuT3duZXIgIT0gbmlsIHsKCQl1c2Vyc1RvTm90aWZ5ID0gYXBwZW5kKHVzZXJzVG9Ob3RpZnksIHN0cnVjdCB7CgkJCXVzZXIgICBVc2VyCgkJCXJlYXNvbiBOb3RpZmljYXRpb25SZWFzb24KCQl9eypldmVudC5Pd25lciwgUmVhc29uT3duZXJ9KQoJfQoKCS8vIFJlbW92ZSB0aGUgYWN0b3IKCXVzZXJzVG9Ob3RpZnkgPSBwLmZpbHRlck91dEFjdG9yKHVzZXJzVG9Ob3RpZnksIGV2ZW50LkFjdG9yKQoKCXAuc2VuZE5vdGlmaWNhdGlvbnMoY3R4LCBldmVudCwgdXNlcnNUb05vdGlmeSkKfQoKLy8gSGFuZGxlUHVsbFJlcXVlc3RDb21tZW50IHByb2Nlc3NlcyBQUiBjb21tZW50IGV2ZW50cwpmdW5jIChwICpQcm9jZXNzb3IpIEhhbmRsZVB1bGxSZXF1ZXN0Q29tbWVudChlICp3ZWJob29rLlB1bGxSZXF1ZXN0Q29tbWVudEV2ZW50KSB7CgljdHggOj0gY29udGV4dC5CYWNrZ3JvdW5kKCkKCWV2ZW50IDo9IHAubm9ybWFsaXplUFJDb21tZW50RXZlbnQoZSkKCglpZiBlLkFjdGlvbiAhPSAiY3JlYXRlZCIgewoJCXJldHVybiAvLyBPbmx5IG5vdGlmeSBvbiBuZXcgY29tbWVudHMKCX0KCgl2YXIgdXNlcnNUb05vdGlmeSBbXXN0cnVjdCB7CgkJdXNlciAgIFVzZXIKCQlyZWFzb24gTm90aWZpY2F0aW9uUmVhc29uCgl9CgoJLy8gTm90aWZ5IFBSIG93bmVyCglpZiBwLmNmZy5SdWxlcy5Db21tZW50Lk5vdGlmeVRocmVhZE93bmVyICYmIGV2ZW50Lk93bmVyICE9IG5pbCB7CgkJdXNlcnNUb05vdGlmeSA9IGFwcGVuZCh1c2Vyc1RvTm90aWZ5LCBzdHJ1Y3QgewoJCQl1c2VyICAgVXNlcgoJCQlyZWFzb24gTm90aWZpY2F0aW9uUmVhc29uCgkJfXsqZXZlbnQuT3duZXIsIFJlYXNvbk93bmVyfSkKCX0KCgkvLyBFeHRyYWN0IGFuZCBub3RpZnkgbWVudGlvbmVkIHVzZXJzCglpZiBwLmNmZy5SdWxlcy5Db21tZW50Lk5vdGlmeU1lbnRpb25lZCB7CgkJbWVudGlvbmVkVXNlcnMgOj0gRXh0cmFjdE1lbnRpb25zKGUuQ29tbWVudC5Cb2R5KQoJCWZvciBfLCB1c2VybmFtZSA6PSByYW5nZSBtZW50aW9uZWRVc2VycyB7CgkJCXVzZXJzVG9Ob3RpZnkgPSBhcHBlbmQodXNlcnNUb05vdGlmeSwgc3RydWN0IHsKCQkJCXVzZXIgICBVc2VyCgkJCQlyZWFzb24gTm90aWZpY2F0aW9uUmVhc29uCgkJCX17VXNlcntHaXRlYVVzZXJuYW1lOiB1c2VybmFtZX0sIFJlYXNvbk1lbnRpb259KQoJCX0KCX0KCgkvLyBOb3RpZnkgcmV2aWV3ZXJzCglpZiBwLmNmZy5SdWxlcy5Db21tZW50Lk5vdGlmeVJldmlld2VycyB7CgkJZm9yIF8sIHUgOj0gcmFuZ2UgZXZlbnQuUmV2aWV3ZXJzIHsKCQkJdXNlcnNUb05vdGlmeSA9IGFwcGVuZCh1c2Vyc1RvTm90aWZ5LCBzdHJ1Y3QgewoJCQkJdXNlciAgIFVzZXIKCQkJCXJlYXNvbiBOb3RpZmljYXRpb25SZWFzb24KCQkJfXt1LCBSZWFzb25SZXZpZXdlcn0pCgkJfQoJfQoKCS8vIFJlbW92ZSB0aGUgYWN0b3IKCXVzZXJzVG9Ob3RpZnkgPSBwLmZpbHRlck91dEFjdG9yKHVzZXJzVG9Ob3RpZnksIGV2ZW50LkFjdG9yKQoKCXAuc2VuZE5vdGlmaWNhdGlvbnMoY3R4LCBldmVudCwgdXNlcnNUb05vdGlmeSkKfQoKLy8gSGFuZGxlSXNzdWUgcHJvY2Vzc2VzIGlzc3VlIGV2ZW50cwpmdW5jIChwICpQcm9jZXNzb3IpIEhhbmRsZUlzc3VlKGUgKndlYmhvb2suSXNzdWVFdmVudCkgewoJY3R4IDo9IGNvbnRleHQuQmFja2dyb3VuZCgpCglldmVudCA6PSBwLm5vcm1hbGl6ZUlzc3VlRXZlbnQoZSkKCgl2YXIgdXNlcnNUb05vdGlmeSBbXXN0cnVjdCB7CgkJdXNlciAgIFVzZXIKCQlyZWFzb24gTm90aWZpY2F0aW9uUmVhc29uCgl9CgoJc3dpdGNoIGUuQWN0aW9uIHsKCWNhc2UgIm9wZW5lZCI6CgkJZXZlbnQuVHlwZSA9IFR5cGVJc3N1ZU9wZW5lZAoJCS8vIE5vdGlmeSBhc3NpZ25lZXMKCQlpZiBwLmNmZy5SdWxlcy5Jc3N1ZS5Ob3RpZnlBc3NpZ25lZXMgewoJCQlmb3IgXywgdSA6PSByYW5nZSBldmVudC5Bc3NpZ25lZXMgewoJCQkJdXNlcnNUb05vdGlmeSA9IGFwcGVuZCh1c2Vyc1RvTm90aWZ5LCBzdHJ1Y3QgewoJCQkJCXVzZXIgICBVc2VyCgkJCQkJcmVhc29uIE5vdGlmaWNhdGlvblJlYXNvbgoJCQkJfXt1LCBSZWFzb25Bc3NpZ25lZX0pCgkJCX0KCQl9CgoJY2FzZSAiY2xvc2VkIjoKCQlldmVudC5UeXBlID0gVHlwZUlzc3VlQ2xvc2VkCgkJLy8gTm90aWZ5IG93bmVyCgkJaWYgZXZlbnQuT3duZXIgIT0gbmlsIHsKCQkJdXNlcnNUb05vdGlmeSA9IGFwcGVuZCh1c2Vyc1RvTm90aWZ5LCBzdHJ1Y3QgewoJCQkJdXNlciAgIFVzZXIKCQkJCXJlYXNvbiBOb3RpZmljYXRpb25SZWFzb24KCQkJfXsqZXZlbnQuT3duZXIsIFJlYXNvbk93bmVyfSkKCQl9Cgl9CgoJLy8gUmVtb3ZlIHRoZSBhY3RvcgoJdXNlcnNUb05vdGlmeSA9IHAuZmlsdGVyT3V0QWN0b3IodXNlcnNUb05vdGlmeSwgZXZlbnQuQWN0b3IpCgoJcC5zZW5kTm90aWZpY2F0aW9ucyhjdHgsIGV2ZW50LCB1c2Vyc1RvTm90aWZ5KQp9CgovLyBIYW5kbGVJc3N1ZUNvbW1lbnQgcHJvY2Vzc2VzIGlzc3VlIGNvbW1lbnQgZXZlbnRzCmZ1bmMgKHAgKlByb2Nlc3NvcikgSGFuZGxlSXNzdWVDb21tZW50KGUgKndlYmhvb2suSXNzdWVDb21tZW50RXZlbnQpIHsKCWN0eCA6PSBjb250ZXh0LkJhY2tncm91bmQoKQoJZXZlbnQgOj0gcC5ub3JtYWxpemVJc3N1ZUNvbW1lbnRFdmVudChlKQoKCWlmIGUuQWN0aW9uICE9ICJjcmVhdGVkIiB7CgkJcmV0dXJuCgl9CgoJdmFyIHVzZXJzVG9Ob3RpZnkgW11zdHJ1Y3QgewoJCXVzZXIgICBVc2VyCgkJcmVhc29uIE5vdGlmaWNhdGlvblJlYXNvbgoJfQoKCS8vIE5vdGlmeSBpc3N1ZSBvd25lcgoJaWYgcC5jZmcuUnVsZXMuQ29tbWVudC5Ob3RpZnlUaHJlYWRPd25lciAmJiBldmVudC5Pd25lciAhPSBuaWwgewoJCXVzZXJzVG9Ob3RpZnkgPSBhcHBlbmQodXNlcnNUb05vdGlmeSwgc3RydWN0IHsKCQkJdXNlciAgIFVzZXIKCQkJcmVhc29uIE5vdGlmaWNhdGlvblJlYXNvbgoJCX17KmV2ZW50Lk93bmVyLCBSZWFzb25Pd25lcn0pCgl9CgoJLy8gRXh0cmFjdCBhbmQgbm90aWZ5IG1lbnRpb25lZCB1c2VycwoJaWYgcC5jZmcuUnVsZXMuQ29tbWVudC5Ob3RpZnlNZW50aW9uZWQgewoJCW1lbnRpb25lZFVzZXJzIDo9IEV4dHJhY3RNZW50aW9ucyhlLkNvbW1lbnQuQm9keSkKCQlmb3IgXywgdXNlcm5hbWUgOj0gcmFuZ2UgbWVudGlvbmVkVXNlcnMgewoJCQl1c2Vyc1RvTm90aWZ5ID0gYXBwZW5kKHVzZXJzVG9Ob3RpZnksIHN0cnVjdCB7CgkJCQl1c2VyICAgVXNlcgoJCQkJcmVhc29uIE5vdGlmaWNhdGlvblJlYXNvbgoJCQl9e1VzZXJ7R2l0ZWFVc2VybmFtZTogdXNlcm5hbWV9LCBSZWFzb25NZW50aW9ufSkKCQl9Cgl9CgoJLy8gUmVtb3ZlIHRoZSBhY3RvcgoJdXNlcnNUb05vdGlmeSA9IHAuZmlsdGVyT3V0QWN0b3IodXNlcnNUb05vdGlmeSwgZXZlbnQuQWN0b3IpCgoJcC5zZW5kTm90aWZpY2F0aW9ucyhjdHgsIGV2ZW50LCB1c2Vyc1RvTm90aWZ5KQp9CgovLyBzZW5kTm90aWZpY2F0aW9ucyByZXNvbHZlcyB1c2VycyBhbmQgc2VuZHMgbm90aWZpY2F0aW9ucwpmdW5jIChwICpQcm9jZXNzb3IpIHNlbmROb3RpZmljYXRpb25zKGN0eCBjb250ZXh0LkNvbnRleHQsIGV2ZW50ICpFdmVudCwgdXNlcnMgW11zdHJ1Y3QgewoJdXNlciAgIFVzZXIKCXJlYXNvbiBOb3RpZmljYXRpb25SZWFzb24KfSkgewoJLy8gRGVkdXBsaWNhdGUgdXNlcnMKCXNlZW4gOj0gbWFrZShtYXBbc3RyaW5nXWJvb2wpCgoJZm9yIF8sIHUgOj0gcmFuZ2UgdXNlcnMgewoJCWtleSA6PSB1LnVzZXIuR2l0ZWFVc2VybmFtZQoJCWlmIGtleSA9PSAiIiB7CgkJCWtleSA9IHUudXNlci5FbWFpbAoJCX0KCQlpZiBzZWVuW2tleV0gewoJCQljb250aW51ZQoJCX0KCQlzZWVuW2tleV0gPSB0cnVlCgoJCS8vIFJlc29sdmUgdXNlciBpZGVudGl0eQoJCWlkZW50aXR5LCBlcnIgOj0gcC5yZXNvbHZlci5SZXNvbHZlKGN0eCwgdS51c2VyKQoJCWlmIGVyciAhPSBuaWwgewoJCQlwLmxvZ2dlci5XYXJuKCkuCgkJCQlFcnIoZXJyKS4KCQkJCVN0cigidXNlcm5hbWUiLCB1LnVzZXIuR2l0ZWFVc2VybmFtZSkuCgkJCQlNc2coImZhaWxlZCB0byByZXNvbHZlIHVzZXIgaWRlbnRpdHkiKQoJCQljb250aW51ZQoJCX0KCgkJaWYgaWRlbnRpdHkuU2xhY2tJRCA9PSAiIiB7CgkJCXAubG9nZ2VyLkluZm8oKS4KCQkJCVN0cigidXNlcm5hbWUiLCB1LnVzZXIuR2l0ZWFVc2VybmFtZSkuCgkJCQlNc2coInVzZXIgaGFzIG5vIFNsYWNrIElELCBza2lwcGluZyBub3RpZmljYXRpb24iKQoJCQljb250aW51ZQoJCX0KCgkJLy8gQ3JlYXRlIG5vdGlmaWNhdGlvbgoJCW5vdGlmaWNhdGlvbiA6PSAmTm90aWZpY2F0aW9uewoJCQlUYXJnZXRVc2VyOiB1LnVzZXIsCgkJCUV2ZW50OiAgICAgIGV2ZW50LAoJCQlSZWFzb246ICAgICB1LnJlYXNvbiwKCQkJTWVzc2FnZTogICAgcC5mb3JtYXRNZXNzYWdlKGV2ZW50LCB1LnJlYXNvbiksCgkJfQoKCQkvLyBTZW5kIERNdKCJaZiBlcnIgOj0gcC5ub3RpZmllci5TZW5kRGlyZWN0KGN0eCwgaWRlbnRpdHkuU2xhY2tJRCwgbm90aWZpY2F0aW9uKTsgZXJyICE9IG5pbCB7CgkJCXAubG9nZ2VyLkVycm9yKCkuCgkJCQlFcnIoZXJyKS4KCQkJCVN0cigic2xhY2tfaWQiLCBpZGVudGl0eS5TbGFja0lEKS4KCQkJCU1zZygiZmFpbGVkIHRvIHNlbmQgbm90aWZpY2F0aW9uIikKCQl9IGVsc2UgewoJCQlwLmxvZ2dlci5JbmZvKCkuCgkJCQlTdHIoInNsYWNrX2lkIiwgaWRlbnRpdHkuU2xhY2tJRCkuCgkJCQlTdHIoInJlYXNvbiIsIHN0cmluZyh1LnJlYXNvbikpLgoJCQkJU3RyKCJldmVudF90eXBlIiwgc3RyaW5nKGV2ZW50LlR5cGUpKS4KCQkJCU1zZygibm90aWZpY2F0aW9uIHNlbnQiKQoJCX0KCX0KfQoKLy8gZmlsdGVyT3V0QWN0b3IgcmVtb3ZlcyB0aGUgZXZlbnQgYWN0b3IgZnJvbSB0aGUgbm90aWZpY2F0aW9uIGxpc3QKZnVuYyAocCAqUHJvY2Vzc29yKSBmaWx0ZXJPdXRBY3Rvcih1c2VycyBbXXN0cnVjdCB7Cgl1c2VyICAgVXNlcgoJcmVhc29uIE5vdGlmaWNhdGlvblJlYXNvbgp9LCBhY3RvciBVc2VyKSBbXXN0cnVjdCB7Cgl1c2VyICAgVXNlcgoJcmVhc29uIE5vdGlmaWNhdGlvblJlYXNvbgp9IHsKCXZhciBmaWx0ZXJlZCBbXXN0cnVjdCB7CgkJdXNlciAgIFVzZXIKCQlyZWFzb24gTm90aWZpY2F0aW9uUmVhc29uCgl9Cglmb3IgXywgdSA6PSByYW5nZSB1c2VycyB7CgkJaWYgdS51c2VyLkdpdGVhVXNlcm5hbWUgIT0gYWN0b3IuR2l0ZWFVc2VybmFtZSB7CgkJCWZpbHRlcmVkID0gYXBwZW5kKGZpbHRlcmVkLCB1KQoJCX0KCX0KCXJldHVybiBmaWx0ZXJlZAp9CgovLyBmb3JtYXRNZXNzYWdlIGNyZWF0ZXMgYSBodW1hbi1yZWFkYWJsZSBub3RpZmljYXRpb24gbWVzc2FnZQpmdW5jIChwICpQcm9jZXNzb3IpIGZvcm1hdE1lc3NhZ2UoZXZlbnQgKkV2ZW50LCByZWFzb24gTm90aWZpY2F0aW9uUmVhc29uKSBzdHJpbmcgewoJLy8gVGhpcyB3aWxsIGJlIGVuaGFuY2VkIGxhdGVyIHdpdGggdGVtcGxhdGVzCglzd2l0Y2ggZXZlbnQuVHlwZSB7CgljYXNlIFR5cGVQUk9wZW5lZDoKCQlyZXR1cm4gIk5ldyBQUiBvcGVuZWQiCgljYXNlIFR5cGVQUkNsb3NlZDoKCQlyZXR1cm4gIlBSIGNsb3NlZCIKCWNhc2UgVHlwZVBSTWVyZ2VkOgoJCXJldHVybiAiUFIgbWVyZ2VkIgoJY2FzZSBUeXBlUFJSZXZpZXdSZXF1ZXN0ZWQ6CgkJcmV0dXJuICJSZXZpZXcgcmVxdWVzdGVkIgoJY2FzZSBUeXBlUFJSZXZpZXdlZDoKCQlyZXR1cm4gIlBSIHJldmlld2VkIgoJY2FzZSBUeXBlUFJDb21tZW50ZWQ6CgkJcmV0dXJuICJOZXcgY29tbWVudCBvbiBQUiIKCWNhc2UgVHlwZUlzc3VlT3BlbmVkOgoJCXJldHVybiAiTmV3IGlzc3VlIG9wZW5lZCIKCWNhc2UgVHlwZUlzc3VlQ2xvc2VkOgoJCXJldHVybiAiSXNzdWUgY2xvc2VkIgoJY2FzZSBUeXBlSXNzdWVDb21tZW50ZWQ6CgkJcmV0dXJuICJOZXcgY29tbWVudCBvbiBpc3N1ZSIKCWRlZmF1bHQ6CgkJcmV0dXJuICJOZXcgbm90aWZpY2F0aW9uIgoJfQp9CgovLyBOb3JtYWxpemF0aW9uIGhlbHBlcnMKZnVuYyAocCAqUHJvY2Vzc29yKSBub3JtYWxpemVQUkV2ZW50KGUgKndlYmhvb2suUHVsbFJlcXVlc3RFdmVudCkgKkV2ZW50IHsKCW93bmVyIDo9IGdpdGVhVXNlclRvVXNlcihlLlB1bGxSZXF1ZXN0LlVzZXIpCgoJLy8gR2V0IHJldmlld2VycyBmcm9tIGJvdGggcG9zc2libGUgbG9jYXRpb25zOgoJLy8gLSBlLlB1bGxSZXF1ZXN0LlJlcXVlc3RlZFJldmlld2VyczogcHJlc2VudCBpbiBvcGVuZWQgYWN0aW9uCgkvLyAtIGUuUmVxdWVzdGVkUmV2aWV3ZXJzOiBwcmVzZW50IGluIHJldmlld19yZXF1ZXN0ZWQgYWN0aW9uCgl2YXIgcmV2aWV3ZXJzIFtdVXNlcgoJaWYgbGVuKGUuUHVsbFJlcXVlc3QuUmVxdWVzdGVkUmV2aWV3ZXJzKSA+IDAgewoJCXJldmlld2VycyA9IGdpdGVhVXNlcnNUb1VzZXJzKGUuUHVsbFJlcXVlc3QuUmVxdWVzdGVkUmV2aWV3ZXJzKQoJfSBlbHNlIGlmIGxlbihlLlJlcXVlc3RlZFJldmlld2VycykgPiAwIHsKCQlyZXZpZXdlcnMgPSBnaXRlYVVzZXJzVG9Vc2VycyhlLlJlcXVlc3RlZFJldmlld2VycykKCX0KCglyZXR1cm4gJkV2ZW50ewoJCVRpbWVzdGFtcDogICAgdGltZS5Ob3coKSwKCQlBY3RvcjogICAgICAgIGdpdGVhVXNlclRvVXNlcihlLlNlbmRlciksCgkJUmVwb05hbWU6ICAgICBlLlJlcG9zaXRvcnkuTmFtZSwKCQlSZXBvRnVsbE5hbWU6IGUuUmVwb3NpdG9yeS5GdWxsTmFtZSwKCQlSZXBvVVJMOiAgICAgIGUuUmVwb3NpdG9yeS5IVE1MVVJMLAoJCU51bWJlcjogICAgICAgZS5QdWxsUmVxdWVzdC5OdW1iZXIsCgkJVGl0bGU6ICAgICAgICBlLlB1bGxSZXF1ZXN0LlRpdGxlLAoJCUJvZHk6ICAgICAgICAgZS5QdWxsUmVxdWVzdC5Cb2R5LAoJCVVSTDogICAgICAgICAgZS5QdWxsUmVxdWVzdC5IVE1MVVJMLAoJCU93bmVyOiAgICAgICAgJm93bmVyLAoJCUFzc2lnbmVlczogICAgZ2l0ZWFVc2Vyc1RvVXNlcnMoZS5QdWxsUmVxdWVzdC5Bc3NpZ25lZXMpLAoJCVJldmlld2VyczogICAgcmV2aWV3ZXJzLAoJfQp9CgpmdW5jIChwICpQcm9jZXNzb3IpIG5vcm1hbGl6ZVJldmlld0V2ZW50KGUgKndlYmhvb2suUHVsbFJlcXVlc3RSZXZpZXdFdmVudCkgKkV2ZW50IHsKCW93bmVyIDo9IGdpdGVhVXNlclRvVXNlcihlLlB1bGxSZXF1ZXN0LlVzZXIpCglyZXR1cm4gJkV2ZW50ewoJCVR5cGU6ICAgICAgICAgVHlwZVBSUmV2aWV3ZWQsCgkJVGltZXN0YW1wOiAgICB0aW1lLk5vdygpLAoJCUFjdG9yOiAgICAgICAgZ2l0ZWFVc2VyVG9Vc2VyKGUuU2VuZGVyKSwKCQlSZXBvTmFtZTogICAgIGUuUmVwb3NpdG9yeS5OYW1lLAoJCVJlcG9GdWxsTmFtZTogZS5SZXBvc2l0b3J5LkZ1bGxOYW1lLAoJCVJlcG9VUkw6ICAgICAgZS5SZXBvc2l0b3J5LkhUTUxVUkwsCgkJTnVtYmVyOiAgICAgICBlLlB1bGxSZXF1ZXN0Lk51bWJlciwKCQlUaXRsZTogICAgICAgIGUuUHVsbFJlcXVlc3QuVGl0bGUsCgkJVVJMOiAgICAgICAgICBlLlB1bGxSZXF1ZXN0LkhUTUxVUkwsCgkJT3duZXI6ICAgICAgICAmb3duZXIsCgkJUmV2aWV3U3RhdGU6ICBlLlJldmlldy5TdGF0ZSwKCQlDb21tZW50Qm9keTogIGUuUmV2aWV3LkJvZHksCgl9Cn0KCmZ1bmMgKHAgKlByb2Nlc3Nvcikgbm9ybWFsaXplUFJDb21tZW50RXZlbnQoZSAqd2ViaG9vay5QdWxsUmVxdWVzdENvbW1lbnRFdmVudCkgKkV2ZW50IHsKCW93bmVyIDo9IGdpdGVhVXNlclRvVXNlcihlLlB1bGxSZXF1ZXN0LlVzZXIpCglyZXR1cm4gJkV2ZW50ewoJCVR5cGU6ICAgICAgICAgVHlwZVBSQ29tbWVudGVkLAoJCVRpbWVzdGFtcDogICAgdGltZS5Ob3coKSwKCQlBY3RvcjogICAgICAgIGdpdGVhVXNlclRvVXNlcihlLlNlbmRlciksCgkJUmVwb05hbWU6ICAgICBlLlJlcG9zaXRvcnkuTmFtZSwKCQlSZXBvRnVsbE5hbWU6IGUuUmVwb3NpdG9yeS5GdWxsTmFtZSwKCQlSZXBvVVJMOiAgICAgIGUuUmVwb3NpdG9yeS5IVE1MVVJMLAoJCU51bWJlcjogICAgICAgZS5QdWxsUmVxdWVzdC5OdW1iZXIsCgkJVGl0bGU6ICAgICAgICBlLlB1bGxSZXF1ZXN0LlRpdGxlLAoJCVVSTDogICAgICAgICAgZS5QdWxsUmVxdWVzdC5IVE1MVVJMLAoJCU93bmVyOiAgICAgICAgJm93bmVyLAoJCVJldmlld2VyczogICAgZ2l0ZWFVc2Vyc1RvVXNlcnMoZS5QdWxsUmVxdWVzdC5SZXF1ZXN0ZWRSZXZpZXdlcnMpLAoJCUNvbW1lbnRCb2R5OiAgZS5Db21tZW50LkJvZHksCgkJQ29tbWVudFVSTDogICBlLkNvbW1lbnQuSFRNTFVSTCwKCX0KfQoKZnVuYyAocCAqUHJvY2Vzc29yKSBub3JtYWxpemVJc3N1ZUV2ZW50KGUgKndlYmhvb2suSXNzdWVFdmVudCkgKkV2ZW50IHsKCW93bmVyIDo9IGdpdGVhVXNlclRvVXNlcihlLklzc3VlLlVzZXIpCglyZXR1cm4gJkV2ZW50ewoJCVRpbWVzdGFtcDogICAgdGltZS5Ob3coKSwKCQlBY3RvcjogICAgICAgIGdpdGVhVXNlclRvVXNlcihlLlNlbmRlciksCgkJUmVwb05hbWU6ICAgICBlLlJlcG9zaXRvcnkuTmFtZSwKCQlSZXBvRnVsbE5hbWU6IGUuUmVwb3NpdG9yeS5GdWxsTmFtZSwKCQlSZXBvVVJMOiAgICAgIGUuUmVwb3NpdG9yeS5IVE1MVVJMLAoJCU51bWJlcjogICAgICAgZS5Jc3N1ZS5OdW1iZXIsCgkJVGl0bGU6ICAgICAgICBlLklzc3VlLlRpdGxlLAoJCVVSTDogICAgICAgICAgZS5Jc3N1ZS5IVE1MVVJMLAoJCU93bmVyOiAgICAgICAgJm93bmVyLAoJCUFzc2lnbmVlczogICAgZ2l0ZWFVc2Vyc1RvVXNlcnMoZS5Jc3N1ZS5Bc3NpZ25lZXMpLAoJfQp9CgpmdW5jIChwICpQcm9jZXNzb3IpIG5vcm1hbGl6ZUlzc3VlQ29tbWVudEV2ZW50KGUgKndlYmhvb2suSXNzdWVDb21tZW50RXZlbnQpICpFdmVudCB7Cglvd25lciA6PSBnaXRlYVVzZXJUb1VzZXIoZS5Jc3N1ZS5Vc2VyKQoJcmV0dXJuICZFdmVudHsKCQlUeXBlOiAgICAgICAgIFR5cGVJc3N1ZUNvbW1lbnRlZCwKCQlUaW1lc3RhbXA6ICAgIHRpbWUuTm93KCksCgkJRXZlbnRHb2FsOiAgICBkZWZpbmVkLAoJCUFjdG9yOiAgICAgICAgZ2l0ZWFVc2VyVG9Vc2VyKGUuU2VuZGVyKSwKCQlSZXBvTmFtZTogICAgIGUuUmVwb3NpdG9yeS5OYW1lLAoJCVJlcG9GdWxsTmFtZTogZS5SZXBvc2l0b3J5LkZ1bGxOYW1lLAoJCVJlcG9VUkw6ICAgICAgZS5SZXBvc2l0b3J5LkhUTUxVUkwsCgkJTnVtYmVyOiAgICAgICBlLklzc3VlLk51bWJlciwKCQlUaXRsZTogICAgICAgIGUuSXNzdWUuVGl0bGUsCgkJQm9keTogICAgICAgICBlLklzc3VlLkJvZHksCgkJVVJMOiAgICAgICAgICBlLklzc3VlLkhUTUxVUkwsCgkJT3duZXI6ICAgICAgICAmb3duZXIsCgkJQXNzaWduZWVzOiAgICBnaXRlYVVzZXJzVG9Vc2VycyhlLklzc3VlLkFzc2lnbmVlcyksCgkJQ29tbWVudEJvZHk6ICBlLkNvbW1lbnQuQm9keSwKCQlDb21tZW50VVJMOiAgIGUuQ29tbWVudC5IVE1MVVJMLAoJfQp9CgpmdW5jIGdpdGVhVXNlclRvVXNlcih1IHdlYmhvb2suR2l0ZWFVc2VyKSBVc2VyIHsKCXVzZXJuYW1lIDo9IHUuTG9naW4KCWlmIHVzZXJuYW1lID09ICIiIHsKCQl1c2VybmFtZSA9IHUuVXNlcm5hbWUKCX0KCXJldHVybiBVc2VyewoJCUdpdGVhSUQ6ICAgICAgIHUuSUQsCgkJR2l0ZWFVc2VybmFtZTogdXNlcm5hbWUsCgkJRW1haWw6ICAgICAgICAgdS5FbWFpbCwKCQlGdWxsTmFtZTogICAgICB1LkZ1bGxOYW1lLAoJfQp9CgpmdW5jIGdpdGVhVXNlcnNUb1VzZXJzKHVzZXJzIFtdd2ViaG9vay5HaXRlYVVzZXIpIFtdVXNlciB7CglyZXN1bHQgPSBtYWtlKFtdVXNlciwgbGVuKHVzZXJzKSkKCWZvciBpLCB1IDo9IHJhbmdlIHVzZXJzIHsKCQlyZXN1bHRbaV0gPSBnaXRlYVVzZXJUb1VzZXIodSkKCX0KCXJldHVybiByZXN1bHQKfQo=