IiIiY29kZWZyYWdtZW50cy5weSAtLSB3cmFwcGVyIHRvIG1vZGlmeSBjb2RlIGZyYWdtZW50cy4iIiIKCiMgqSAxOTk4LCBKdXN0IHZhbiBSb3NzdW0sIExldHRlcnJvcgoKX192ZXJzaW9uX18gPSAiMC44YjMiCl9fYXV0aG9yX18gPSAianZyIgoKaW1wb3J0IG1hY2ZzCmltcG9ydCBzdHJ1Y3QKZnJvbSBDYXJib24gaW1wb3J0IFJlcwppbXBvcnQgb3MKaW1wb3J0IHN5cwoKREVCVUcgPSAwCgplcnJvciA9ICJjZm0uZXJyb3IiCgpCVUZTSVpFID0gMHg4MDAwMAoKZGVmIG1lcmdlY2ZtZmlsZXMoc3JjbGlzdCwgZHN0LCBhcmNoaXRlY3R1cmUgPSAnZmF0Jyk6CgkiIiJNZXJnZSBhbGwgZmlsZXMgaW4gc3JjbGlzdCBpbnRvIGEgbmV3IGZpbGUgZHN0LiAKCQoJSWYgYXJjaGl0ZWN0dXJlIGlzIGdpdmVuLCBvbmx5IGNvZGUgZnJhZ21lbnRzIG9mIHRoYXQgdHlwZSB3aWxsIGJlIHVzZWQ6CgkicHdwYyIgZm9yIFBQQywgIm02OGsiIGZvciBjZm02OGsuIFRoaXMgZG9lcyBub3Qgd29yayBmb3IgImNsYXNzaWMiCgk2OGsgY29kZSwgc2luY2UgaXQgZG9lcyBub3QgdXNlIGNvZGUgZnJhZ21lbnRzIHRvIGJlZ2luIHdpdGguCglJZiBhcmNoaXRlY3R1cmUgaXMgTm9uZSwgYWxsIGZyYWdtZW50cyB3aWxsIGJlIHVzZWQsIGVuYWJsaW5nIEZBVCBiaW5hcmllcy4KCSIiIgoJCglzcmNsaXN0ID0gbGlzdChzcmNsaXN0KQoJZm9yIGkgaW4gcmFuZ2UobGVuKHNyY2xpc3QpKToKCQlpZiB0eXBlKHNyY2xpc3RbaV0pID09IG1hY2ZzLkZTU3BlY1R5cGU6CgkJCXNyY2xpc3RbaV0gPSBzcmNsaXN0W2ldLmFzX3BhdGhuYW1lKCkKCWlmIHR5cGUoZHN0KSA9PSBtYWNmcy5GU1NwZWNUeXBlOgoJCWRzdCA9IGRzdC5hc19wYXRobmFtZSgpCgkKCWRzdGZpbGUgPSBvcGVuKGRzdCwgIndiIikKCXJmID0gUmVzLkZTcE9wZW5SZXNGaWxlKGRzdCwgMykKCXRyeToKCQlkc3RjZnJnID0gQ2ZyZ1Jlc291cmNlKCkKCQlmb3Igc3JjIGluIHNyY2xpc3Q6CgkJCXNyY2NmcmcgPSBDZnJnUmVzb3VyY2Uoc3JjKQoJCQlmb3IgZnJhZyBpbiBzcmNjZnJnLmZyYWdtZW50czoKCQkJCWlmIGZyYWcuYXJjaGl0ZWN0dXJlID09ICdwd3BjJyBhbmQgYXJjaGl0ZWN0dXJlID09ICdtNjhrJzoKCQkJCQljb250aW51ZQoJCQkJaWYgZnJhZy5hcmNoaXRlY3R1cmUgPT0gJ202OGsnIGFuZCBhcmNoaXRlY3R1cmUgPT0gJ3B3cGMnOgoJCQkJCWNvbnRpbnVlCgkJCQlkc3RjZnJnLmFwcGVuZChmcmFnKQoJCQkJCgkJCQlmcmFnLmNvcHlkYXRhKGRzdGZpbGUpCgkJCQkKCQljZnJncmVzID0gUmVzLlJlc291cmNlKGRzdGNmcmcuYnVpbGQoKSkKCQlSZXMuVXNlUmVzRmlsZShyZikKCQljZnJncmVzLkFkZFJlc291cmNlKCdjZnJnJywgMCwgIiIpCglmaW5hbGx5OgoJCWRzdGZpbGUuY2xvc2UoKQoJCXJmID0gUmVzLkNsb3NlUmVzRmlsZShyZikKCgpjbGFzcyBDZnJnUmVzb3VyY2U6CgkKCWRlZiBfX2luaXRfXyhzZWxmLCBwYXRoID0gTm9uZSk6CgkJc2VsZi52ZXJzaW9uID0gMQoJCXNlbGYuZnJhZ21lbnRzID0gW10KCQlzZWxmLnBhdGggPSBwYXRoCgkJaWYgcGF0aCBpcyBub3QgTm9uZSBhbmQgb3MucGF0aC5leGlzdHMocGF0aCk6CgkJCWN1cnJlbnRyZXNyZWYgPSBSZXMuQ3VyUmVzRmlsZSgpCgkJCXJlc3JlZiA9IFJlcy5GU3BPcGVuUmVzRmlsZShwYXRoLCAxKQoJCQlSZXMuVXNlUmVzRmlsZShyZXNyZWYpCgkJCXRyeToKCQkJCXRyeToKCQkJCQlkYXRhID0gUmVzLkdldDFSZXNvdXJjZSgnY2ZyZycsIDApLmRhdGEKCQkJCWV4Y2VwdCBSZXMuRXJyb3I6CgkJCQkJcmFpc2UgUmVzLkVycm9yLCAibm8glWNmcmfVIHJlc291cmNlIGZvdW5kIiwgc3lzLmV4Y190cmFjZWJhY2sKCQkJZmluYWxseToKCQkJCVJlcy5DbG9zZVJlc0ZpbGUocmVzcmVmKQoJCQkJUmVzLlVzZVJlc0ZpbGUoY3VycmVudHJlc3JlZikKCQkJc2VsZi5wYXJzZShkYXRhKQoJCQlpZiBzZWxmLnZlcnNpb24gPD4gMToKCQkJCXJhaXNlIGVycm9yLCAidW5rbm93biAnY2ZyZycgcmVzb3VyY2UgZm9ybWF0IgkKCQoJZGVmIHBhcnNlKHNlbGYsIGRhdGEpOgoJCShyZXMxLCByZXMyLCBzZWxmLnZlcnNpb24sIAoJCQlyZXMzLCByZXM0LCByZXM1LCByZXM2LCAKCQkJc2VsZi5tZW1iZXJDb3VudCkgPSBzdHJ1Y3QudW5wYWNrKCI4bCIsIGRhdGFbOjMyXSkKCQlkYXRhID0gZGF0YVszMjpdCgkJd2hpbGUgZGF0YToKCQkJZnJhZyA9IEZyYWdtZW50RGVzY3JpcHRvcihzZWxmLnBhdGgsIGRhdGEpCgkJCWRhdGEgPSBkYXRhW2ZyYWcubWVtYmVyU2l6ZTpdCgkJCXNlbGYuZnJhZ21lbnRzLmFwcGVuZChmcmFnKQoJCglkZWYgYnVpbGQoc2VsZik6CgkJc2VsZi5tZW1iZXJDb3VudCA9IGxlbihzZWxmLmZyYWdtZW50cykKCQlkYXRhID0gc3RydWN0LnBhY2soIjhsIiwgMCwgMCwgc2VsZi52ZXJzaW9uLCAwLCAwLCAwLCAwLCBzZWxmLm1lbWJlckNvdW50KQoJCWZvciBmcmFnIGluIHNlbGYuZnJhZ21lbnRzOgoJCQlkYXRhID0gZGF0YSArIGZyYWcuYnVpbGQoKQoJCXJldHVybiBkYXRhCgkKCWRlZiBhcHBlbmQoc2VsZiwgZnJhZyk6CgkJc2VsZi5mcmFnbWVudHMuYXBwZW5kKGZyYWcpCgoKY2xhc3MgRnJhZ21lbnREZXNjcmlwdG9yOgoJCglkZWYgX19pbml0X18oc2VsZiwgcGF0aCwgZGF0YSA9IE5vbmUpOgoJCXNlbGYucGF0aCA9IHBhdGgKCQlpZiBkYXRhIGlzIG5vdCBOb25lOgoJCQlzZWxmLnBhcnNlKGRhdGEpCgkKCWRlZiBwYXJzZShzZWxmLCBkYXRhKToKCQlzZWxmLmFyY2hpdGVjdHVyZSA9IGRhdGFbOjRdCgkJKAlzZWxmLnVwZGF0ZWxldmVsLCAKCQkJc2VsZi5jdXJyZW50VmVyc2lvbiwgCgkJCXNlbGYub2xkRGVmVmVyc2lvbiwgCgkJCXNlbGYuc3RhY2tzaXplLAoJCQlzZWxmLmFwcGxpYmRpciwgCgkJCXNlbGYuZnJhZ3R5cGUsCgkJCXNlbGYud2hlcmUsCgkJCXNlbGYub2Zmc2V0LAoJCQlzZWxmLmxlbmd0aCwKCQkJc2VsZi5yZXMxLCBzZWxmLnJlczIsCgkJCXNlbGYubWVtYmVyU2l6ZSwpID0gc3RydWN0LnVucGFjaygiNGxoQkI0bGgiLCBkYXRhWzQ6NDJdKQoJCXBuYW1lID0gZGF0YVs0MjpzZWxmLm1lbWJlclNpemVdCgkJc2VsZi5uYW1lID0gcG5hbWVbMToxK29yZChwbmFtZVswXSldCgkKCWRlZiBidWlsZChzZWxmKToKCQlkYXRhID0gc2VsZi5hcmNoaXRlY3R1cmUKCQlkYXRhID0gZGF0YSArIHN0cnVjdC5wYWNrKCI0bGhCQjRsIiwKCQkJCXNlbGYudXBkYXRlbGV2ZWwsIAoJCQkJc2VsZi5jdXJyZW50VmVyc2lvbiwgCgkJCQlzZWxmLm9sZERlZlZlcnNpb24sIAoJCQkJc2VsZi5zdGFja3NpemUsCgkJCQlzZWxmLmFwcGxpYmRpciwgCgkJCQlzZWxmLmZyYWd0eXBlLAoJCQkJc2VsZi53aGVyZSwKCQkJCXNlbGYub2Zmc2V0LAoJCQkJc2VsZi5sZW5ndGgsCgkJCQlzZWxmLnJlczEsIHNlbGYucmVzMikKCQlzZWxmLm1lbWJlclNpemUgPSBsZW4oZGF0YSkgKyAyICsgMSArIGxlbihzZWxmLm5hbWUpCgkJIyBwYWQgdG8gNCBieXRlIGJvdW5kYXJpZXMKCQlpZiBzZWxmLm1lbWJlclNpemUgJSA0OgoJCQlzZWxmLm1lbWJlclNpemUgPSBzZWxmLm1lbWJlclNpemUgKyA0IC0gKHNlbGYubWVtYmVyU2l6ZSAlIDQpCgkJZGF0YSA9IGRhdGEgKyBzdHJ1Y3QucGFjaygiaGIiLCBzZWxmLm1lbWJlclNpemUsIGxlbihzZWxmLm5hbWUpKQoJCWRhdGEgPSBkYXRhICsgc2VsZi5uYW1lCgkJZGF0YSA9IGRhdGEgKyAnXDAwMCcgKiAoc2VsZi5tZW1iZXJTaXplIC0gbGVuKGRhdGEpKQoJCXJldHVybiBkYXRhCgkKCWRlZiBnZXRmcmFnbWVudChzZWxmKToKCQlpZiBzZWxmLndoZXJlIDw+IDE6CgkJCXJhaXNlIGVycm9yLCAiY2Fu1XQgcmVhZCBmcmFnbWVudCwgdW5zdXBwb3J0ZWQgbG9jYXRpb24iCgkJZiA9IG9wZW4oc2VsZi5wYXRoLCAicmIiKQoJCWYuc2VlayhzZWxmLm9mZnNldCkKCQlpZiBzZWxmLmxlbmd0aDoKCQkJZnJhZyA9IGYucmVhZChzZWxmLmxlbmd0aCkKCQllbHNlOgoJCQlmcmFnID0gZi5yZWFkKCkKCQlmLmNsb3NlKCkKCQlyZXR1cm4gZnJhZwoJCglkZWYgY29weWRhdGEoc2VsZiwgb3V0ZmlsZSk6CgkJaWYgc2VsZi53aGVyZSA8PiAxOgoJCQlyYWlzZSBlcnJvciwgImNhbtV0IHJlYWQgZnJhZ21lbnQsIHVuc3VwcG9ydGVkIGxvY2F0aW9uIgoJCWluZmlsZSA9IG9wZW4oc2VsZi5wYXRoLCAicmIiKQoJCWlmIHNlbGYubGVuZ3RoID09IDA6CgkJCWluZmlsZS5zZWVrKDAsIDIpCgkJCXNlbGYubGVuZ3RoID0gaW5maWxlLnRlbGwoKQoJCQoJCSMgUG9zaXRpb24gaW5wdXQgZmlsZSBhbmQgcmVjb3JkIG5ldyBvZmZzZXQgZnJvbSBvdXRwdXQgZmlsZQoJCWluZmlsZS5zZWVrKHNlbGYub2Zmc2V0KQoJCQoJCSMgcGFkIHRvIDE2IGJ5dGUgYm91bmRhcmllcwoJCW9mZnNldCA9IG91dGZpbGUudGVsbCgpCgkJaWYgb2Zmc2V0ICUgMTY6CgkJCW9mZnNldCA9IG9mZnNldCArIDE2IC0gKG9mZnNldCAlIDE2KQoJCW91dGZpbGUuc2VlayhvZmZzZXQpCgkJc2VsZi5vZmZzZXQgPSBvZmZzZXQKCQkKCQlsID0gc2VsZi5sZW5ndGgKCQl3aGlsZSBsOgoJCQlpZiBsID4gQlVGU0laRToKCQkJCW91dGZpbGUud3JpdGUoaW5maWxlLnJlYWQoQlVGU0laRSkpCgkJCQlsID0gbCAtIEJVRlNJWkUKCQkJZWxzZToKCQkJCW91dGZpbGUud3JpdGUoaW5maWxlLnJlYWQobCkpCgkJCQlsID0gMAoJCWluZmlsZS5jbG9zZSgpCgo=