IyAtKi0gY29kaW5nOiBpc28tODg1OS0xIC0qLQoiIiIgQSBTQVgyIGRyaXZlciBmb3IgbGlieG1sMiwgb24gdG9wIG9mIGl0J3MgWG1sUmVhZGVyIEFQSQoKVVNBR0UKICAgICMgcHV0IHRoaXMgZmlsZSAoZHJ2X2xpYnhtbDIucHkpIGluIFBZVEhPTlBBVEgKICAgIGltcG9ydCB4bWwuc2F4CiAgICByZWFkZXIgPSB4bWwuc2F4Lm1ha2VfcGFyc2VyKFsiZHJ2X2xpYnhtbDIiXSkKICAgICMgLi4uYW5kIHRoZSByZXN0IGlzIHN0YW5kYXJkIHB5dGhvbiBzYXguCgpDQVZFQVRTCiAgICAtIExleGljYWwgaGFuZGxlcnMgYXJlIHN1cHBvcnRlZCwgZXhjZXB0IGZvciBzdGFydC9lbmRFbnRpdHkKICAgICAgKHdhaXRpbmcgZm9yIFhtbFJlYWRlci5SZXNvbHZlRW50aXR5KSBhbmQgc3RhcnQvZW5kRFRECiAgICAtIEVycm9yIGNhbGxiYWNrcyBhcmUgbm90IGV4YWN0bHkgc3luY2hyb25vdXMsIHRoZXkgdGVuZAogICAgICB0byBiZSBpbnZva2VkIGJlZm9yZSB0aGUgY29ycmVzcG9uZGluZyBjb250ZW50IGNhbGxiYWNrLAogICAgICBiZWNhdXNlIHRoZSB1bmRlcmx5aW5nIHJlYWRlciBpbnRlcmZhY2UgcGFyc2VzCiAgICAgIGRhdGEgYnkgY2h1bmtzIG9mIDUxMiBieXRlcwogICAgClRPRE8KICAgIC0gc2VhcmNoIGZvciBUT0RPCiAgICAtIHNvbWUgRXJyb3JIYW5kbGVyIGV2ZW50cyAod2FybmluZykKICAgIC0gc29tZSBDb250ZW50SGFuZGxlciBldmVudHMgKHNldERvY3VtZW50TG9jYXRvciwgc2tpcHBlZEVudGl0eSkKICAgIC0gRW50aXR5UmVzb2x2ZXIgKHVzaW5nIGxpYnhtbDIuPykKICAgIC0gRFRESGFuZGxlciAoaWYvd2hlbiBsaWJ4bWwyIGV4cG9zZXMgc3VjaCBub2RlIHR5cGVzKQogICAgLSBEZWNsSGFuZGxlciAoaWYvd2hlbiBsaWJ4bWwyIGV4cG9zZXMgc3VjaCBub2RlIHR5cGVzKQogICAgLSBwcm9wZXJ0eV94bWxfc3RyaW5nPwogICAgLSBmZWF0dXJlX3N0cmluZ19pbnRlcm5pbmc/CiAgICAtIEluY3JlbWVudGFsIHBhcnNlcgogICAgLSBhZGRpdGlvbmFsIHBlcmZvcm1hbmNlIHR1bmluZzoKICAgICAgLSBvbmUgbWlnaHQgY2FjaGUgY2FsbGJhY2tzIHRvIGF2b2lkIHNvbWUgbmFtZSBsb29rdXBzCiAgICAgIC0gb25lIG1pZ2h0IGltcGxlbWVudCBhIHNtYXJ0ZXIgd2F5IHRvIHBhc3MgYXR0cmlidXRlcyB0byBzdGFydEVsZW1lbnQKICAgICAgICAoc29tZSBraW5kIG9mIGxhenkgZXZhbHVhdGlvbj8pCiAgICAgIC0gdGhlcmUgbWlnaHQgYmUgcm9vbSBmb3IgaW1wcm92ZW1lbnQgaW4gc3RhcnQvZW5kUHJlZml4TWFwcGluZwogICAgICAtIG90aGVyPwoKIiIiCgpfX2F1dGhvcl9fICA9ICJTdOlwaGFuZSBCaWRvdWwgPHNiaUBza3luZXQuYmU+IgpfX3ZlcnNpb25fXyA9ICIwLjMiCgppbXBvcnQgc3lzCmltcG9ydCBjb2RlY3MKCmlmIHN5cy52ZXJzaW9uX2luZm9bMF0gPCAzOgogICAgX19hdXRob3JfXyAgPSBjb2RlY3MudW5pY29kZV9lc2NhcGVfZGVjb2RlKF9fYXV0aG9yX18pWzBdCgogICAgU3RyaW5nVHlwZXMgPSAoc3RyLCB1bmljb2RlKQogICAgIyBsaWJ4bWwyIHJldHVybnMgc3RyaW5ncyBhcyBVVEY4CiAgICBfZGVjb2RlciA9IGNvZGVjcy5sb29rdXAoInV0ZjgiKVsxXQogICAgZGVmIF9kKHMpOgogICAgICAgIGlmIHMgaXMgTm9uZToKICAgICAgICAgICAgcmV0dXJuIHMKICAgICAgICBlbHNlOgogICAgICAgICAgICByZXR1cm4gX2RlY29kZXIocylbMF0KZWxzZToKICAgIFN0cmluZ1R5cGVzID0gc3RyCiAgICAjIHMgaXMgVW5pY29kZSBgc3RyYCBhbHJlYWR5CiAgICBkZWYgX2Qocyk6CiAgICAgICAgcmV0dXJuIHMKCmZyb20geG1sLnNheC5fZXhjZXB0aW9ucyBpbXBvcnQgKgpmcm9tIHhtbC5zYXggaW1wb3J0IHhtbHJlYWRlciwgc2F4dXRpbHMKZnJvbSB4bWwuc2F4LmhhbmRsZXIgaW1wb3J0IFwKICAgICBmZWF0dXJlX25hbWVzcGFjZXMsIFwKICAgICBmZWF0dXJlX25hbWVzcGFjZV9wcmVmaXhlcywgXAogICAgIGZlYXR1cmVfc3RyaW5nX2ludGVybmluZywgXAogICAgIGZlYXR1cmVfdmFsaWRhdGlvbiwgXAogICAgIGZlYXR1cmVfZXh0ZXJuYWxfZ2VzLCBcCiAgICAgZmVhdHVyZV9leHRlcm5hbF9wZXMsIFwKICAgICBwcm9wZXJ0eV9sZXhpY2FsX2hhbmRsZXIsIFwKICAgICBwcm9wZXJ0eV9kZWNsYXJhdGlvbl9oYW5kbGVyLCBcCiAgICAgcHJvcGVydHlfZG9tX25vZGUsIFwKICAgICBwcm9wZXJ0eV94bWxfc3RyaW5nCgp0cnk6CiAgICBpbXBvcnQgbGlieG1sMgpleGNlcHQgSW1wb3J0RXJyb3I6CiAgICByYWlzZSBTQVhSZWFkZXJOb3RBdmFpbGFibGUoImxpYnhtbDIgbm90IGF2YWlsYWJsZTogIiBcCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImltcG9ydCBlcnJvciB3YXM6ICVzIiAlIHN5cy5leGNfaW5mbygpWzFdKQoKY2xhc3MgTG9jYXRvcih4bWxyZWFkZXIuTG9jYXRvcik6CiAgICAiIiJTQVggTG9jYXRvciBhZGFwdGVyIGZvciBsaWJ4bWwyLnhtbFRleHRSZWFkZXJMb2NhdG9yIiIiCgogICAgZGVmIF9faW5pdF9fKHNlbGYsbG9jYXRvcik6CiAgICAgICAgc2VsZi5fX2xvY2F0b3IgPSBsb2NhdG9yCgogICAgZGVmIGdldENvbHVtbk51bWJlcihzZWxmKToKICAgICAgICAiUmV0dXJuIHRoZSBjb2x1bW4gbnVtYmVyIHdoZXJlIHRoZSBjdXJyZW50IGV2ZW50IGVuZHMuIgogICAgICAgIHJldHVybiAtMQoKICAgIGRlZiBnZXRMaW5lTnVtYmVyKHNlbGYpOgogICAgICAgICJSZXR1cm4gdGhlIGxpbmUgbnVtYmVyIHdoZXJlIHRoZSBjdXJyZW50IGV2ZW50IGVuZHMuIgogICAgICAgIHJldHVybiBzZWxmLl9fbG9jYXRvci5MaW5lTnVtYmVyKCkKCiAgICBkZWYgZ2V0UHVibGljSWQoc2VsZik6CiAgICAgICAgIlJldHVybiB0aGUgcHVibGljIGlkZW50aWZpZXIgZm9yIHRoZSBjdXJyZW50IGV2ZW50LiIKICAgICAgICByZXR1cm4gTm9uZQoKICAgIGRlZiBnZXRTeXN0ZW1JZChzZWxmKToKICAgICAgICAiUmV0dXJuIHRoZSBzeXN0ZW0gaWRlbnRpZmllciBmb3IgdGhlIGN1cnJlbnQgZXZlbnQuIgogICAgICAgIHJldHVybiBzZWxmLl9fbG9jYXRvci5CYXNlVVJJKCkKCmNsYXNzIExpYlhtbDJSZWFkZXIoeG1scmVhZGVyLlhNTFJlYWRlcik6CgogICAgZGVmIF9faW5pdF9fKHNlbGYpOgogICAgICAgIHhtbHJlYWRlci5YTUxSZWFkZXIuX19pbml0X18oc2VsZikKICAgICAgICAjIGZlYXR1cmVzCiAgICAgICAgc2VsZi5fX25zID0gMAogICAgICAgIHNlbGYuX19uc3BmeCA9IDAKICAgICAgICBzZWxmLl9fdmFsaWRhdGUgPSAwCiAgICAgICAgc2VsZi5fX2V4dHBhcmFtcyA9IDEKICAgICAgICAjIHBhcnNpbmcgZmxhZwogICAgICAgIHNlbGYuX19wYXJzaW5nID0gMAogICAgICAgICMgYWRkaXRpb25hbCBoYW5kbGVycwogICAgICAgIHNlbGYuX19sZXhfaGFuZGxlciA9IE5vbmUKICAgICAgICBzZWxmLl9fZGVjbF9oYW5kbGVyID0gTm9uZQogICAgICAgICMgZXJyb3IgbWVzc2FnZXMgYWNjdW11bGF0b3IKICAgICAgICBzZWxmLl9fZXJyb3JzID0gTm9uZQoKICAgIGRlZiBfZXJyb3JIYW5kbGVyKHNlbGYsYXJnLG1zZyxzZXZlcml0eSxsb2NhdG9yKToKICAgICAgICBpZiBzZWxmLl9fZXJyb3JzIGlzIE5vbmU6CiAgICAgICAgICAgIHNlbGYuX19lcnJvcnMgPSBbXQogICAgICAgIHNlbGYuX19lcnJvcnMuYXBwZW5kKChzZXZlcml0eSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgU0FYUGFyc2VFeGNlcHRpb24obXNnLE5vbmUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIExvY2F0b3IobG9jYXRvcikpKSkKCiAgICBkZWYgX3JlcG9ydEVycm9ycyhzZWxmLGZhdGFsKToKICAgICAgICBmb3Igc2V2ZXJpdHksZXhjZXB0aW9uIGluIHNlbGYuX19lcnJvcnM6CiAgICAgICAgICAgIGlmIHNldmVyaXR5IGluIChsaWJ4bWwyLlBBUlNFUl9TRVZFUklUWV9WQUxJRElUWV9XQVJOSU5HLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlieG1sMi5QQVJTRVJfU0VWRVJJVFlfV0FSTklORyk6CiAgICAgICAgICAgICAgICBzZWxmLl9lcnJfaGFuZGxlci53YXJuaW5nKGV4Y2VwdGlvbikKICAgICAgICAgICAgZWxzZToKICAgICAgICAgICAgICAgICMgd2hlbiBmYXRhbCBpcyBzZXQsIHRoZSBwYXJzZSB3aWxsIHN0b3A7CiAgICAgICAgICAgICAgICAjIHdlIGNvbnNpZGVyIHRoYXQgdGhlIGxhc3QgZXJyb3IgcmVwb3J0ZWQKICAgICAgICAgICAgICAgICMgaXMgdGhlIGZhdGFsIG9uZS4KICAgICAgICAgICAgICAgIGlmIGZhdGFsIGFuZCBleGNlcHRpb24gaXMgc2VsZi5fX2Vycm9yc1stMV1bMV06CiAgICAgICAgICAgICAgICAgICAgc2VsZi5fZXJyX2hhbmRsZXIuZmF0YWxFcnJvcihleGNlcHRpb24pCiAgICAgICAgICAgICAgICBlbHNlOgogICAgICAgICAgICAgICAgICAgIHNlbGYuX2Vycl9oYW5kbGVyLmVycm9yKGV4Y2VwdGlvbikKICAgICAgICBzZWxmLl9fZXJyb3JzID0gTm9uZQoKICAgIGRlZiBwYXJzZShzZWxmLCBzb3VyY2UpOgogICAgICAgIHNlbGYuX19wYXJzaW5nID0gMQogICAgICAgIHRyeToKICAgICAgICAgICAgIyBwcmVwYXJlIHNvdXJjZSBhbmQgY3JlYXRlIHJlYWRlcgogICAgICAgICAgICBpZiBpc2luc3RhbmNlKHNvdXJjZSwgU3RyaW5nVHlwZXMpOgogICAgICAgICAgICAgICAgcmVhZGVyID0gbGlieG1sMi5uZXdUZXh0UmVhZGVyRmlsZW5hbWUoc291cmNlKQogICAgICAgICAgICBlbHNlOgogICAgICAgICAgICAgICAgc291cmNlID0gc2F4dXRpbHMucHJlcGFyZV9pbnB1dF9zb3VyY2Uoc291cmNlKQogICAgICAgICAgICAgICAgc3RyZWFtID0gc291cmNlLmdldENoYXJhY3RlclN0cmVhbSgpCiAgICAgICAgICAgICAgICBpZiBzdHJlYW0gaXMgTm9uZToKICAgICAgICAgICAgICAgICAgICBzdHJlYW0gPSBzb3VyY2UuZ2V0Qnl0ZVN0cmVhbSgpCiAgICAgICAgICAgICAgICBpbnB1dCA9IGxpYnhtbDIuaW5wdXRCdWZmZXIoc3RyZWFtKQogICAgICAgICAgICAgICAgcmVhZGVyID0gaW5wdXQubmV3VGV4dFJlYWRlcihzb3VyY2UuZ2V0U3lzdGVtSWQoKSkKICAgICAgICAgICAgcmVhZGVyLlNldEVycm9ySGFuZGxlcihzZWxmLl9lcnJvckhhbmRsZXIsTm9uZSkKICAgICAgICAgICAgIyBjb25maWd1cmUgcmVhZGVyCiAgICAgICAgICAgIGlmIHNlbGYuX19leHRwYXJhbXM6CiAgICAgICAgICAgICAgICByZWFkZXIuU2V0UGFyc2VyUHJvcChsaWJ4bWwyLlBBUlNFUl9MT0FERFRELDEpCiAgICAgICAgICAgICAgICByZWFkZXIuU2V0UGFyc2VyUHJvcChsaWJ4bWwyLlBBUlNFUl9ERUZBVUxUQVRUUlMsMSkKICAgICAgICAgICAgICAgIHJlYWRlci5TZXRQYXJzZXJQcm9wKGxpYnhtbDIuUEFSU0VSX1NVQlNUX0VOVElUSUVTLDEpCiAgICAgICAgICAgICAgICByZWFkZXIuU2V0UGFyc2VyUHJvcChsaWJ4bWwyLlBBUlNFUl9WQUxJREFURSxzZWxmLl9fdmFsaWRhdGUpCiAgICAgICAgICAgIGVsc2U6CiAgICAgICAgICAgICAgICByZWFkZXIuU2V0UGFyc2VyUHJvcChsaWJ4bWwyLlBBUlNFUl9MT0FERFRELCAwKQogICAgICAgICAgICAjIHdlIHJldXNlIGF0dHJpYnV0ZSBtYXBzIChmb3IgYSBzbGlnaHQgcGVyZm9ybWFuY2UgZ2FpbikKICAgICAgICAgICAgaWYgc2VsZi5fX25zOgogICAgICAgICAgICAgICAgYXR0cmlidXRlc05TSW1wbCA9IHhtbHJlYWRlci5BdHRyaWJ1dGVzTlNJbXBsKHt9LHt9KQogICAgICAgICAgICBlbHNlOgogICAgICAgICAgICAgICAgYXR0cmlidXRlc0ltcGwgPSB4bWxyZWFkZXIuQXR0cmlidXRlc0ltcGwoe30pCiAgICAgICAgICAgICMgcHJlZml4ZXMgdG8gcG9wIChmb3IgZW5kUHJlZml4TWFwcGluZykKICAgICAgICAgICAgcHJlZml4ZXMgPSBbXQogICAgICAgICAgICAjIHN0YXJ0IGxvb3AKICAgICAgICAgICAgc2VsZi5fY29udF9oYW5kbGVyLnN0YXJ0RG9jdW1lbnQoKQogICAgICAgICAgICB3aGlsZSAxOgogICAgICAgICAgICAgICAgciA9IHJlYWRlci5SZWFkKCkKICAgICAgICAgICAgICAgICMgY2hlY2sgZm9yIGVycm9ycwogICAgICAgICAgICAgICAgaWYgciA9PSAxOgogICAgICAgICAgICAgICAgICAgIGlmIG5vdCBzZWxmLl9fZXJyb3JzIGlzIE5vbmU6CiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX3JlcG9ydEVycm9ycygwKQogICAgICAgICAgICAgICAgZWxpZiByID09IDA6CiAgICAgICAgICAgICAgICAgICAgaWYgbm90IHNlbGYuX19lcnJvcnMgaXMgTm9uZToKICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5fcmVwb3J0RXJyb3JzKDApCiAgICAgICAgICAgICAgICAgICAgYnJlYWsgIyBlbmQgb2YgcGFyc2UKICAgICAgICAgICAgICAgIGVsc2U6CiAgICAgICAgICAgICAgICAgICAgaWYgbm90IHNlbGYuX19lcnJvcnMgaXMgTm9uZToKICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5fcmVwb3J0RXJyb3JzKDEpCiAgICAgICAgICAgICAgICAgICAgZWxzZToKICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5fZXJyX2hhbmRsZXIuZmF0YWxFcnJvcihcCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBTQVhFeGNlcHRpb24oIlJlYWQgZmFpbGVkIChubyBkZXRhaWxzIGF2YWlsYWJsZSkiKSkKICAgICAgICAgICAgICAgICAgICBicmVhayAjIGZhdGFsIHBhcnNlIGVycm9yCiAgICAgICAgICAgICAgICAjIGdldCBub2RlIHR5cGUKICAgICAgICAgICAgICAgIG5vZGVUeXBlID0gcmVhZGVyLk5vZGVUeXBlKCkKICAgICAgICAgICAgICAgICMgRWxlbWVudAogICAgICAgICAgICAgICAgaWYgbm9kZVR5cGUgPT0gMTogCiAgICAgICAgICAgICAgICAgICAgaWYgc2VsZi5fX25zOgogICAgICAgICAgICAgICAgICAgICAgICBlbHROYW1lID0gKF9kKHJlYWRlci5OYW1lc3BhY2VVcmkoKSksXAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIF9kKHJlYWRlci5Mb2NhbE5hbWUoKSkpCiAgICAgICAgICAgICAgICAgICAgICAgIGVsdFFOYW1lID0gX2QocmVhZGVyLk5hbWUoKSkKICAgICAgICAgICAgICAgICAgICAgICAgYXR0cmlidXRlc05TSW1wbC5fYXR0cnMgPSBhdHRycyA9IHt9CiAgICAgICAgICAgICAgICAgICAgICAgIGF0dHJpYnV0ZXNOU0ltcGwuX3FuYW1lcyA9IHFuYW1lcyA9IHt9CiAgICAgICAgICAgICAgICAgICAgICAgIG5ld1ByZWZpeGVzID0gW10KICAgICAgICAgICAgICAgICAgICAgICAgd2hpbGUgcmVhZGVyLk1vdmVUb05leHRBdHRyaWJ1dGUoKToKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHFuYW1lID0gX2QocmVhZGVyLk5hbWUoKSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlID0gX2QocmVhZGVyLlZhbHVlKCkpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiBxbmFtZS5zdGFydHN3aXRoKCJ4bWxucyIpOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIGxlbihxbmFtZSkgPiA1OgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdQcmVmaXggPSBxbmFtZVs2Ol0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdQcmVmaXggPSBOb25lCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3UHJlZml4ZXMuYXBwZW5kKG5ld1ByZWZpeCkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxmLl9jb250X2hhbmRsZXIuc3RhcnRQcmVmaXhNYXBwaW5nKFwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3UHJlZml4LHZhbHVlKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIG5vdCBzZWxmLl9fbnNwZng6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlICMgZG9uJ3QgcmVwb3J0IHhtbG5zIGF0dHJpYnV0ZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgYXR0TmFtZSA9IChfZChyZWFkZXIuTmFtZXNwYWNlVXJpKCkpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBfZChyZWFkZXIuTG9jYWxOYW1lKCkpKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgcW5hbWVzW2F0dE5hbWVdID0gcW5hbWUKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF0dHJzW2F0dE5hbWVdID0gdmFsdWUKICAgICAgICAgICAgICAgICAgICAgICAgcmVhZGVyLk1vdmVUb0VsZW1lbnQoKQogICAgICAgICAgICAgICAgICAgICAgICBzZWxmLl9jb250X2hhbmRsZXIuc3RhcnRFbGVtZW50TlMoIFwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsdE5hbWUsZWx0UU5hbWUsYXR0cmlidXRlc05TSW1wbCkgCiAgICAgICAgICAgICAgICAgICAgICAgIGlmIHJlYWRlci5Jc0VtcHR5RWxlbWVudCgpOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5fY29udF9oYW5kbGVyLmVuZEVsZW1lbnROUyhlbHROYW1lLGVsdFFOYW1lKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIG5ld1ByZWZpeCBpbiBuZXdQcmVmaXhlczoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxmLl9jb250X2hhbmRsZXIuZW5kUHJlZml4TWFwcGluZyhuZXdQcmVmaXgpCiAgICAgICAgICAgICAgICAgICAgICAgIGVsc2U6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcmVmaXhlcy5hcHBlbmQobmV3UHJlZml4ZXMpCiAgICAgICAgICAgICAgICAgICAgZWxzZToKICAgICAgICAgICAgICAgICAgICAgICAgZWx0TmFtZSA9IF9kKHJlYWRlci5OYW1lKCkpCiAgICAgICAgICAgICAgICAgICAgICAgIGF0dHJpYnV0ZXNJbXBsLl9hdHRycyA9IGF0dHJzID0ge30KICAgICAgICAgICAgICAgICAgICAgICAgd2hpbGUgcmVhZGVyLk1vdmVUb05leHRBdHRyaWJ1dGUoKToKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF0dE5hbWUgPSBfZChyZWFkZXIuTmFtZSgpKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgYXR0cnNbYXR0TmFtZV0gPSBfZChyZWFkZXIuVmFsdWUoKSkKICAgICAgICAgICAgICAgICAgICAgICAgcmVhZGVyLk1vdmVUb0VsZW1lbnQoKQogICAgICAgICAgICAgICAgICAgICAgICBzZWxmLl9jb250X2hhbmRsZXIuc3RhcnRFbGVtZW50KCBcCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHROYW1lLGF0dHJpYnV0ZXNJbXBsKQogICAgICAgICAgICAgICAgICAgICAgICBpZiByZWFkZXIuSXNFbXB0eUVsZW1lbnQoKToKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX2NvbnRfaGFuZGxlci5lbmRFbGVtZW50KGVsdE5hbWUpCiAgICAgICAgICAgICAgICAjIEVuZEVsZW1lbnQKICAgICAgICAgICAgICAgIGVsaWYgbm9kZVR5cGUgPT0gMTU6IAogICAgICAgICAgICAgICAgICAgIGlmIHNlbGYuX19uczoKICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5fY29udF9oYW5kbGVyLmVuZEVsZW1lbnROUyggXAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIChfZChyZWFkZXIuTmFtZXNwYWNlVXJpKCkpLF9kKHJlYWRlci5Mb2NhbE5hbWUoKSkpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIF9kKHJlYWRlci5OYW1lKCkpKQogICAgICAgICAgICAgICAgICAgICAgICBmb3IgcHJlZml4IGluIHByZWZpeGVzLnBvcCgpOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5fY29udF9oYW5kbGVyLmVuZFByZWZpeE1hcHBpbmcocHJlZml4KQogICAgICAgICAgICAgICAgICAgIGVsc2U6CiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX2NvbnRfaGFuZGxlci5lbmRFbGVtZW50KF9kKHJlYWRlci5OYW1lKCkpKQogICAgICAgICAgICAgICAgIyBUZXh0CiAgICAgICAgICAgICAgICBlbGlmIG5vZGVUeXBlID09IDM6IAogICAgICAgICAgICAgICAgICAgIHNlbGYuX2NvbnRfaGFuZGxlci5jaGFyYWN0ZXJzKF9kKHJlYWRlci5WYWx1ZSgpKSkKICAgICAgICAgICAgICAgICMgV2hpdGVzcGFjZQogICAgICAgICAgICAgICAgZWxpZiBub2RlVHlwZSA9PSAxMzogCiAgICAgICAgICAgICAgICAgICAgc2VsZi5fY29udF9oYW5kbGVyLmlnbm9yYWJsZVdoaXRlc3BhY2UoX2QocmVhZGVyLlZhbHVlKCkpKQogICAgICAgICAgICAgICAgIyBTaWduaWZpY2FudFdoaXRlc3BhY2UKICAgICAgICAgICAgICAgIGVsaWYgbm9kZVR5cGUgPT0gMTQ6CiAgICAgICAgICAgICAgICAgICAgc2VsZi5fY29udF9oYW5kbGVyLmNoYXJhY3RlcnMoX2QocmVhZGVyLlZhbHVlKCkpKQogICAgICAgICAgICAgICAgIyBDREFUQQogICAgICAgICAgICAgICAgZWxpZiBub2RlVHlwZSA9PSA0OgogICAgICAgICAgICAgICAgICAgIGlmIG5vdCBzZWxmLl9fbGV4X2hhbmRsZXIgaXMgTm9uZToKICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5fX2xleF9oYW5kbGVyLnN0YXJ0Q0RBVEEoKQogICAgICAgICAgICAgICAgICAgIHNlbGYuX2NvbnRfaGFuZGxlci5jaGFyYWN0ZXJzKF9kKHJlYWRlci5WYWx1ZSgpKSkKICAgICAgICAgICAgICAgICAgICBpZiBub3Qgc2VsZi5fX2xleF9oYW5kbGVyIGlzIE5vbmU6CiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX19sZXhfaGFuZGxlci5lbmRDREFUQSgpCiAgICAgICAgICAgICAgICAjIEVudGl0eVJlZmVyZW5jZQogICAgICAgICAgICAgICAgZWxpZiBub2RlVHlwZSA9PSA1OgogICAgICAgICAgICAgICAgICAgIGlmIG5vdCBzZWxmLl9fbGV4X2hhbmRsZXIgaXMgTm9uZToKICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5zdGFydEVudGl0eShfZChyZWFkZXIuTmFtZSgpKSkKICAgICAgICAgICAgICAgICAgICByZWFkZXIuUmVzb2x2ZUVudGl0eSgpCiAgICAgICAgICAgICAgICAjIEVuZEVudGl0eQogICAgICAgICAgICAgICAgZWxpZiBub2RlVHlwZSA9PSAxNjoKICAgICAgICAgICAgICAgICAgICBpZiBub3Qgc2VsZi5fX2xleF9oYW5kbGVyIGlzIE5vbmU6CiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuZW5kRW50aXR5KF9kKHJlYWRlci5OYW1lKCkpKQogICAgICAgICAgICAgICAgIyBQcm9jZXNzaW5nSW5zdHJ1Y3Rpb24KICAgICAgICAgICAgICAgIGVsaWYgbm9kZVR5cGUgPT0gNzogCiAgICAgICAgICAgICAgICAgICAgc2VsZi5fY29udF9oYW5kbGVyLnByb2Nlc3NpbmdJbnN0cnVjdGlvbiggXAogICAgICAgICAgICAgICAgICAgICAgICBfZChyZWFkZXIuTmFtZSgpKSxfZChyZWFkZXIuVmFsdWUoKSkpCiAgICAgICAgICAgICAgICAjIENvbW1lbnQKICAgICAgICAgICAgICAgIGVsaWYgbm9kZVR5cGUgPT0gODoKICAgICAgICAgICAgICAgICAgICBpZiBub3Qgc2VsZi5fX2xleF9oYW5kbGVyIGlzIE5vbmU6CiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX19sZXhfaGFuZGxlci5jb21tZW50KF9kKHJlYWRlci5WYWx1ZSgpKSkKICAgICAgICAgICAgICAgICMgRG9jdW1lbnRUeXBlCiAgICAgICAgICAgICAgICBlbGlmIG5vZGVUeXBlID09IDEwOgogICAgICAgICAgICAgICAgICAgICNpZiBub3Qgc2VsZi5fX2xleF9oYW5kbGVyIGlzIE5vbmU6CiAgICAgICAgICAgICAgICAgICAgIyAgICBzZWxmLl9fbGV4X2hhbmRsZXIuc3RhcnREVEQoKQogICAgICAgICAgICAgICAgICAgIHBhc3MgIyBUT0RPIChob3cgdG8gZGV0ZWN0IGVuZERURD8gb24gZmlyc3Qgbm9uLWR0ZCBldmVudD8pCiAgICAgICAgICAgICAgICAjIFhtbERlY2xhcmF0aW9uCiAgICAgICAgICAgICAgICBlbGlmIG5vZGVUeXBlID09IDE3OgogICAgICAgICAgICAgICAgICAgIHBhc3MgIyBUT0RPCiAgICAgICAgICAgICAgICAjIEVudGl0eQogICAgICAgICAgICAgICAgZWxpZiBub2RlVHlwZSA9PSA2OgogICAgICAgICAgICAgICAgICAgIHBhc3MgIyBUT0RPIChlbnRpdHkgZGVjbCkKICAgICAgICAgICAgICAgICMgTm90YXRpb24gKGRlY2wpCiAgICAgICAgICAgICAgICBlbGlmIG5vZGVUeXBlID09IDEyOgogICAgICAgICAgICAgICAgICAgIHBhc3MgIyBUT0RPCiAgICAgICAgICAgICAgICAjIEF0dHJpYnV0ZSAobmV2ZXIgaW4gdGhpcyBsb29wKQogICAgICAgICAgICAgICAgI2VsaWYgbm9kZVR5cGUgPT0gMjogCiAgICAgICAgICAgICAgICAjICAgIHBhc3MKICAgICAgICAgICAgICAgICMgRG9jdW1lbnQgKG5vdCBleHBvc2VkKQogICAgICAgICAgICAgICAgI2VsaWYgbm9kZVR5cGUgPT0gOTogCiAgICAgICAgICAgICAgICAjICAgIHBhc3MKICAgICAgICAgICAgICAgICMgRG9jdW1lbnRGcmFnbWVudCAobmV2ZXIgcmV0dXJuZWQgYnkgWG1sUmVhZGVyKQogICAgICAgICAgICAgICAgI2VsaWYgbm9kZVR5cGUgPT0gMTE6CiAgICAgICAgICAgICAgICAjICAgIHBhc3MKICAgICAgICAgICAgICAgICMgTm9uZQogICAgICAgICAgICAgICAgI2VsaWYgbm9kZVR5cGUgPT0gMDoKICAgICAgICAgICAgICAgICMgICAgcGFzcwogICAgICAgICAgICAgICAgIyAtCiAgICAgICAgICAgICAgICBlbHNlOgogICAgICAgICAgICAgICAgICAgIHJhaXNlIFNBWEV4Y2VwdGlvbigiVW5leHBlY3RlZCBub2RlIHR5cGUgJWQiICUgbm9kZVR5cGUpCiAgICAgICAgICAgIGlmIHIgPT0gMDoKICAgICAgICAgICAgICAgIHNlbGYuX2NvbnRfaGFuZGxlci5lbmREb2N1bWVudCgpCiAgICAgICAgICAgIHJlYWRlci5DbG9zZSgpCiAgICAgICAgZmluYWxseToKICAgICAgICAgICAgc2VsZi5fX3BhcnNpbmcgPSAwCgogICAgZGVmIHNldERUREhhbmRsZXIoc2VsZiwgaGFuZGxlcik6CiAgICAgICAgIyBUT0RPICh3aGVuIHN1cHBvcnRlZCwgdGhlIGluaGVyaXRlZCBtZXRob2Qgd29ya3MganVzdCBmaW5lKQogICAgICAgIHJhaXNlIFNBWE5vdFN1cHBvcnRlZEV4Y2VwdGlvbigiRFRESGFuZGxlciBub3Qgc3VwcG9ydGVkIikKCiAgICBkZWYgc2V0RW50aXR5UmVzb2x2ZXIoc2VsZiwgcmVzb2x2ZXIpOgogICAgICAgICMgVE9ETyAod2hlbiBzdXBwb3J0ZWQsIHRoZSBpbmhlcml0ZWQgbWV0aG9kIHdvcmtzIGp1c3QgZmluZSkKICAgICAgICByYWlzZSBTQVhOb3RTdXBwb3J0ZWRFeGNlcHRpb24oIkVudGl0eVJlc29sdmVyIG5vdCBzdXBwb3J0ZWQiKQoKICAgIGRlZiBnZXRGZWF0dXJlKHNlbGYsIG5hbWUpOgogICAgICAgIGlmIG5hbWUgPT0gZmVhdHVyZV9uYW1lc3BhY2VzOgogICAgICAgICAgICByZXR1cm4gc2VsZi5fX25zCiAgICAgICAgZWxpZiBuYW1lID09IGZlYXR1cmVfbmFtZXNwYWNlX3ByZWZpeGVzOgogICAgICAgICAgICByZXR1cm4gc2VsZi5fX25zcGZ4CiAgICAgICAgZWxpZiBuYW1lID09IGZlYXR1cmVfdmFsaWRhdGlvbjoKICAgICAgICAgICAgcmV0dXJuIHNlbGYuX192YWxpZGF0ZQogICAgICAgIGVsaWYgbmFtZSA9PSBmZWF0dXJlX2V4dGVybmFsX2dlczoKICAgICAgICAgICAgcmV0dXJuIDEgIyBUT0RPIChkb2VzIHRoYXQgcmVsYXRlIHRvIFBBUlNFUl9MT0FERFREKT8KICAgICAgICBlbGlmIG5hbWUgPT0gZmVhdHVyZV9leHRlcm5hbF9wZXM6CiAgICAgICAgICAgIHJldHVybiBzZWxmLl9fZXh0cGFyYW1zCiAgICAgICAgZWxzZToKICAgICAgICAgICAgcmFpc2UgU0FYTm90UmVjb2duaXplZEV4Y2VwdGlvbigiRmVhdHVyZSAnJXMnIG5vdCByZWNvZ25pemVkIiAlIFwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lKQoKICAgIGRlZiBzZXRGZWF0dXJlKHNlbGYsIG5hbWUsIHN0YXRlKToKICAgICAgICBpZiBzZWxmLl9fcGFyc2luZzoKICAgICAgICAgICAgcmFpc2UgU0FYTm90U3VwcG9ydGVkRXhjZXB0aW9uKCJDYW5ub3Qgc2V0IGZlYXR1cmUgJXMgIiBcCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAid2hpbGUgcGFyc2luZyIgJSBuYW1lKQogICAgICAgIGlmIG5hbWUgPT0gZmVhdHVyZV9uYW1lc3BhY2VzOgogICAgICAgICAgICBzZWxmLl9fbnMgPSBzdGF0ZQogICAgICAgIGVsaWYgbmFtZSA9PSBmZWF0dXJlX25hbWVzcGFjZV9wcmVmaXhlczoKICAgICAgICAgICAgc2VsZi5fX25zcGZ4ID0gc3RhdGUKICAgICAgICBlbGlmIG5hbWUgPT0gZmVhdHVyZV92YWxpZGF0aW9uOgogICAgICAgICAgICBzZWxmLl9fdmFsaWRhdGUgPSBzdGF0ZQogICAgICAgIGVsaWYgbmFtZSA9PSBmZWF0dXJlX2V4dGVybmFsX2dlczoKICAgICAgICAgICAgaWYgc3RhdGUgPT0gMDoKICAgICAgICAgICAgICAgICMgVE9ETyAoZG9lcyB0aGF0IHJlbGF0ZSB0byBQQVJTRVJfTE9BRERURCk/CiAgICAgICAgICAgICAgICByYWlzZSBTQVhOb3RTdXBwb3J0ZWRFeGNlcHRpb24oIkZlYXR1cmUgJyVzJyBub3Qgc3VwcG9ydGVkIiAlIFwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lKQogICAgICAgIGVsaWYgbmFtZSA9PSBmZWF0dXJlX2V4dGVybmFsX3BlczoKICAgICAgICAgICAgc2VsZi5fX2V4dHBhcmFtcyA9IHN0YXRlCiAgICAgICAgZWxzZToKICAgICAgICAgICAgcmFpc2UgU0FYTm90UmVjb2duaXplZEV4Y2VwdGlvbigiRmVhdHVyZSAnJXMnIG5vdCByZWNvZ25pemVkIiAlIFwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lKQoKICAgIGRlZiBnZXRQcm9wZXJ0eShzZWxmLCBuYW1lKToKICAgICAgICBpZiBuYW1lID09IHByb3BlcnR5X2xleGljYWxfaGFuZGxlcjoKICAgICAgICAgICAgcmV0dXJuIHNlbGYuX19sZXhfaGFuZGxlcgogICAgICAgIGVsaWYgbmFtZSA9PSBwcm9wZXJ0eV9kZWNsYXJhdGlvbl9oYW5kbGVyOgogICAgICAgICAgICByZXR1cm4gc2VsZi5fX2RlY2xfaGFuZGxlcgogICAgICAgIGVsc2U6CiAgICAgICAgICAgIHJhaXNlIFNBWE5vdFJlY29nbml6ZWRFeGNlcHRpb24oIlByb3BlcnR5ICclcycgbm90IHJlY29nbml6ZWQiICUgXAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hbWUpCgogICAgZGVmIHNldFByb3BlcnR5KHNlbGYsIG5hbWUsIHZhbHVlKTogICAgIAogICAgICAgIGlmIG5hbWUgPT0gcHJvcGVydHlfbGV4aWNhbF9oYW5kbGVyOgogICAgICAgICAgICBzZWxmLl9fbGV4X2hhbmRsZXIgPSB2YWx1ZQogICAgICAgIGVsaWYgbmFtZSA9PSBwcm9wZXJ0eV9kZWNsYXJhdGlvbl9oYW5kbGVyOgogICAgICAgICAgICAjIFRPRE86IHJlbW92ZSBpZi93aGVuIGxpYnhtbDIgc3VwcG9ydHMgZHRkIGV2ZW50cwogICAgICAgICAgICByYWlzZSBTQVhOb3RTdXBwb3J0ZWRFeGNlcHRpb24oIlByb3BlcnR5ICclcycgbm90IHN1cHBvcnRlZCIgJSBcCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lKQogICAgICAgICAgICBzZWxmLl9fZGVjbF9oYW5kbGVyID0gdmFsdWUKICAgICAgICBlbHNlOgogICAgICAgICAgICByYWlzZSBTQVhOb3RSZWNvZ25pemVkRXhjZXB0aW9uKCJQcm9wZXJ0eSAnJXMnIG5vdCByZWNvZ25pemVkIiAlIFwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lKQoKZGVmIGNyZWF0ZV9wYXJzZXIoKToKICAgIHJldHVybiBMaWJYbWwyUmVhZGVyKCkKCg==