IiIiUHl0aG9uU2xhdmUucHkKQW4gYXBwbGljYXRpb24gdGhhdCByZXNwb25kcyB0byB0aHJlZSB0eXBlcyBvZiBhcHBsZSBldmVudDogCgkncHl0aCcvJ0VYRUMnOiAJZXhlY3V0ZSBkaXJlY3QgcGFyYW1ldGVyIGFzIFB5dGhvbgoJJ2FldnQnLCAncXVpdCc6CXF1aXQKCSdhZXZ0JywgJ29kb2MnOglwZXJmb3JtIHB5dGhvbiBzY3JpcHRzCgpDb3B5cmlnaHQgqSAxOTk2LCBKdXN0IHZhbiBSb3NzdW0sIExldHRlcnJvcgoiIiIKCl9fdmVyc2lvbl9fID0gIjAuMS4zIgoKaW1wb3J0IEZyYW1lV29yawppbXBvcnQgc3lzCmltcG9ydCB0cmFjZWJhY2sKaW1wb3J0IGFldG9vbHMKaW1wb3J0IHN0cmluZwppbXBvcnQgQUUKaW1wb3J0IEVhc3lEaWFsb2dzCmltcG9ydCBvcwppbXBvcnQgUWQKZnJvbSBUeXBlcyBpbXBvcnQgKgpmcm9tIEV2ZW50cyBpbXBvcnQgY2hhckNvZGVNYXNrLCBjbWRLZXkKaW1wb3J0IE1hY09TCmltcG9ydCBFdnQKCmRlZiBkdW1teWZ1bmMoKTogcGFzcwoKbW9kdWxlZmlsZW5hbWUgPSBkdW1teWZ1bmMuZnVuY19jb2RlLmNvX2ZpbGVuYW1lCgpkZWYgSW50ZXJhY3QodGltZW91dCA9IDUwMDAwMDAwKToJCQkjIHRpbWVvdXQgYWZ0ZXIgMTAgZGF5cy4uLgoJQUUuQUVJbnRlcmFjdFdpdGhVc2VyKHRpbWVvdXQpCgoKY2xhc3MgUHl0aG9uU2xhdmUoRnJhbWVXb3JrLkFwcGxpY2F0aW9uKToKCWRlZiBfX2luaXRfXyhzZWxmKToKCQlGcmFtZVdvcmsuQXBwbGljYXRpb24uX19pbml0X18oc2VsZikKCQlBRS5BRUluc3RhbGxFdmVudEhhbmRsZXIoJ3B5dGgnLCAnRVhFQycsIEV4ZWNIYW5kbGVyKQoJCUFFLkFFSW5zdGFsbEV2ZW50SGFuZGxlcignYWV2dCcsICdxdWl0JywgUXVpdEhhbmRsZXIpCgkJQUUuQUVJbnN0YWxsRXZlbnRIYW5kbGVyKCdhZXZ0JywgJ29kb2MnLCBPcGVuRG9jdW1lbnRIYW5kbGVyKQoJCglkZWYgbWFrZXVzZXJtZW51cyhzZWxmKToKCQlzZWxmLmZpbGVtZW51ID0gbSA9IEZyYW1lV29yay5NZW51KHNlbGYubWVudWJhciwgIkZpbGUiKQoJCXNlbGYuX3F1aXRpdGVtID0gRnJhbWVXb3JrLk1lbnVJdGVtKG0sICJRdWl0IiwgIlEiLCBzZWxmLl9xdWl0KQoJCglkZWYgZG9fa0hpZ2hMZXZlbEV2ZW50KHNlbGYsIGV2ZW50KToKCQkod2hhdCwgbWVzc2FnZSwgd2hlbiwgd2hlcmUsIG1vZGlmaWVycykgPSBldmVudAoJCXRyeToKCQkJQUUuQUVQcm9jZXNzQXBwbGVFdmVudChldmVudCkKCQlleGNlcHQgQUUuRXJyb3IsIGRldGFpbDoKCQkJcHJpbnQgIkFwcGxlIEV2ZW50IHdhcyBub3QgaGFuZGxlZCwgZXJyb3I6IiwgZGV0YWlsCgkKCWRlZiBkb19rZXkoc2VsZiwgZXZlbnQpOgoJCSh3aGF0LCBtZXNzYWdlLCB3aGVuLCB3aGVyZSwgbW9kaWZpZXJzKSA9IGV2ZW50CgkJYyA9IGNocihtZXNzYWdlICYgY2hhckNvZGVNYXNrKQoJCWlmIG1vZGlmaWVycyAmIGNtZEtleSBhbmQgYyA9PSAnLic6CgkJCXJldHVybgoJCUZyYW1lV29yay5BcHBsaWNhdGlvbi5kb19rZXkoc2VsZiwgZXZlbnQpCgkKCWRlZiBpZGxlKHNlbGYsIGV2ZW50KToKCQlRZC5Jbml0Q3Vyc29yKCkKCQoJZGVmIHF1aXQoc2VsZiwgKmFyZ3MpOgoJCXJhaXNlIHNlbGYKCQoJZGVmIGdldGFib3V0dGV4dChzZWxmKToKCQlyZXR1cm4gIkFib3V0IFB5dGhvblNsYXZlgyIKCQoJZGVmIGRvX2Fib3V0KHNlbGYsIGlkLCBpdGVtLCB3aW5kb3csIGV2ZW50KToKCQlFYXN5RGlhbG9ncy5NZXNzYWdlKCJQeXRob25TbGF2ZSAiICsgX192ZXJzaW9uX18gKyAiXHJDb3B5cmlnaHQgqSAxOTk2LCBMZXR0ZXJyb3IsIEp2UiIpCgkKCmRlZiBFeGVjSGFuZGxlcih0aGVBcHBsZUV2ZW50LCB0aGVSZXBseSk6CglwYXJhbWV0ZXJzLCBhcmdzID0gYWV0b29scy51bnBhY2tldmVudCh0aGVBcHBsZUV2ZW50KQoJaWYgcGFyYW1ldGVycy5oYXNfa2V5KCctLS0tJyk6CgkJaWYgcGFyYW1ldGVycy5oYXNfa2V5KCdOQU1FJyk6CgkJCXByaW50ICctLS0gZXhlY3V0aW5nICInICsgcGFyYW1ldGVyc1snTkFNRSddICsgJyIgLS0tJwoJCWVsc2U6CgkJCXByaW50ICctLS0gZXhlY3V0aW5nICI8dW5rbm93bj4iIC0tLScKCQlzdHVmZiA9IHBhcmFtZXRlcnNbJy0tLS0nXQoJCU15RXhlYyhzdHVmZiArICJcbiIpCQkJIyBleGVjdXRlIGlucHV0CgkJcHJpbnQgJy0tLSBkb25lIC0tLScKCXJldHVybiAwCgpkZWYgTXlFeGVjKHN0dWZmKToKCXN0dWZmID0gc3RyaW5nLnNwbGl0ZmllbGRzKHN0dWZmLCAnXHInKQkjIGNvbnZlcnQgcmV0dXJuIGNoYXJzCglzdHVmZiA9IHN0cmluZy5qb2luZmllbGRzKHN0dWZmLCAnXG4nKQkjIHRvIG5ld2xpbmUgY2hhcnMKCUludGVyYWN0KCkKCXNhdmV5aWVsZCA9IE1hY09TLkVuYWJsZUFwcHN3aXRjaCgxKQoJdHJ5OgoJCWV4ZWMgc3R1ZmYgaW4ge30KCWV4Y2VwdDoKCQlNYWNPUy5FbmFibGVBcHBzd2l0Y2goc2F2ZXlpZWxkKQoJCXRyYWNlYmFjay5wcmludF9leGMoKQoJTWFjT1MuRW5hYmxlQXBwc3dpdGNoKHNhdmV5aWVsZCkKCmRlZiBPcGVuRG9jdW1lbnRIYW5kbGVyKHRoZUFwcGxlRXZlbnQsIHRoZVJlcGx5KToKCXBhcmFtZXRlcnMsIGFyZ3MgPSBhZXRvb2xzLnVucGFja2V2ZW50KHRoZUFwcGxlRXZlbnQpCglkb2NzID0gcGFyYW1ldGVyc1snLS0tLSddCglpZiB0eXBlKGRvY3MpIDw+IExpc3RUeXBlOgoJCWRvY3MgPSBbZG9jc10KCWZvciBkb2MgaW4gZG9jczoKCQlmc3MsIGEgPSBkb2MuUmVzb2x2ZSgpCgkJcGF0aCA9IGZzcy5hc19wYXRobmFtZSgpCgkJaWYgcGF0aCA8PiBtb2R1bGVmaWxlbmFtZToKCQkJTXlFeGVjRmlsZShwYXRoKQoJcmV0dXJuIDAKCmRlZiBNeUV4ZWNGaWxlKHBhdGgpOgoJc2F2ZXlpZWxkID0gTWFjT1MuRW5hYmxlQXBwc3dpdGNoKDEpCglzYXZld2QgPSBvcy5nZXRjd2QoKQoJb3MuY2hkaXIob3MucGF0aC5zcGxpdChwYXRoKVswXSkKCXByaW50ICctLS0gRXhlY3V0aW5nIGZpbGUgIicgKyBvcy5wYXRoLnNwbGl0KHBhdGgpWzFdICsgJyInCgl0cnk6CgkJZXhlY2ZpbGUocGF0aCwgeyJfX25hbWVfXyI6ICJfX21haW5fXyJ9KQoJZXhjZXB0OgoJCXRyYWNlYmFjay5wcmludF9leGMoKQoJCU1hY09TLkVuYWJsZUFwcHN3aXRjaChzYXZleWllbGQpCglNYWNPUy5FbmFibGVBcHBzd2l0Y2goc2F2ZXlpZWxkKQoJb3MuY2hkaXIoc2F2ZXdkKQoJcHJpbnQgIi0tLSBkb25lIC0tLSIKCmRlZiBRdWl0SGFuZGxlcih0aGVBcHBsZUV2ZW50LCB0aGVSZXBseSk6CglzbGF2ZS5xdWl0KCkKCXJldHVybiAwCgoKc2xhdmUgPSBQeXRob25TbGF2ZSgpCnByaW50ICJQeXRob25TbGF2ZSIsIF9fdmVyc2lvbl9fLCAicmVhZHkuIgpzbGF2ZS5tYWlubG9vcCgpCg==