aW1wb3J0IGFldG9vbHMKaW1wb3J0IFN0YW5kYXJkX1N1aXRlCmltcG9ydCBSZXF1aXJlZF9TdWl0ZQppbXBvcnQgV1dXX1N1aXRlCmltcG9ydCByZWdleAppbXBvcnQgVwppbXBvcnQgbWFjZnMKaW1wb3J0IG9zCmltcG9ydCBNYWNQcmVmcwppbXBvcnQgTWFjT1MKaW1wb3J0IHN0cmluZwoKaWYgaGFzYXR0cihXV1dfU3VpdGUsICJXV1dfU3VpdGUiKToKCVdXVyA9IFdXV19TdWl0ZS5XV1dfU3VpdGUKZWxzZToKCVdXVyA9IFdXV19TdWl0ZS5Xb3JsZFdpZGVXZWJfc3VpdGVfMmNfX2FzX2RlZmluZWRfaW5fU3B5Z2xhc3Nfc3BlY18yZV8KCmNsYXNzIFdlYkJyb3dzZXIoYWV0b29scy5UYWxrVG8sIAoJCVN0YW5kYXJkX1N1aXRlLlN0YW5kYXJkX1N1aXRlLCAKCQlXV1cpOgoJCglkZWYgb3BlbmZpbGUoc2VsZiwgcGF0aCwgYWN0aXZhdGUgPSAxKToKCQlpZiBhY3RpdmF0ZToKCQkJc2VsZi5hY3RpdmF0ZSgpCgkJc2VsZi5PcGVuVVJMKCJmaWxlOi8vLyIgKyBzdHJpbmcuam9pbihzdHJpbmcuc3BsaXQocGF0aCwnOicpLCAnLycpKQoKYXBwID0gVy5nZXRhcHBsaWNhdGlvbigpCgojU0lHTkFUVVJFPSdNU0lFJyAjIE1TIEV4cGxvcmVyClNJR05BVFVSRT0nTU9TUycgIyBOZXRzY2FwZQoKX3RpdGxlcGF0ID0gcmVnZXguY29tcGlsZSgnPHRpdGxlPlwoW148XSpcKTwvdGl0bGU+JykKCmRlZiBzdWNrdGl0bGUocGF0aCk6CglmID0gb3BlbihwYXRoKQoJdGV4dCA9IGYucmVhZCgxMDI0KSAjIGFzc3VtZSB0aGUgdGl0bGUgaXMgaW4gdGhlIGZpcnN0IDEwMjQgYnl0ZXMKCWYuY2xvc2UoKQoJbG93ZXJ0ZXh0ID0gc3RyaW5nLmxvd2VyKHRleHQpCglpZiBfdGl0bGVwYXQuc2VhcmNoKGxvd2VydGV4dCkgPiAwOgoJCWEsIGIgPSBfdGl0bGVwYXQucmVnc1sxXQoJCXJldHVybiB0ZXh0W2E6Yl0KCXJldHVybiBwYXRoCgpkZWYgdmVyaWZ5ZG9jcGF0aChkb2NwYXRoKToKCXRyeToKCQl0dXQgPSBvcy5wYXRoLmpvaW4oZG9jcGF0aCwgInR1dCIpCgkJbGliID0gb3MucGF0aC5qb2luKGRvY3BhdGgsICJsaWIiKQoJCXJlZiA9IG9zLnBhdGguam9pbihkb2NwYXRoLCAicmVmIikKCQlmb3IgcGF0aCBpbiBbdHV0LCBsaWIsIHJlZl06CgkJCWlmIG5vdCBvcy5wYXRoLmV4aXN0cyhwYXRoKToKCQkJCXJldHVybiAwCglleGNlcHQ6CgkJcmV0dXJuIDAKCXJldHVybiAxCgoKY2xhc3MgVHdvTGluZUxpc3QoVy5MaXN0KToKCQoJTERFRl9JRCA9IDQ2OAoJCglkZWYgY3JlYXRlbGlzdChzZWxmKToKCQlpbXBvcnQgTGlzdAoJCXNlbGYuX2NhbGNib3VuZHMoKQoJCXNlbGYuU2V0UG9ydCgpCgkJcmVjdCA9IHNlbGYuX2JvdW5kcwoJCXJlY3QgPSByZWN0WzBdKzEsIHJlY3RbMV0rMSwgcmVjdFsyXS0xNiwgcmVjdFszXS0xCgkJc2VsZi5fbGlzdCA9IExpc3QuTE5ldyhyZWN0LCAoMCwgMCwgMSwgMCksICgwLCAyOCksIHNlbGYuTERFRl9JRCwgc2VsZi5fcGFyZW50d2luZG93LndpZCwKCQkJCQkwLCAxLCAwLCAxKQoJCXNlbGYuc2V0KHNlbGYuaXRlbXMpCgoKX3Jlc3VsdHNjb3VudGVyID0gMQoKY2xhc3MgUmVzdWx0czoKCQoJZGVmIF9faW5pdF9fKHNlbGYsIGhpdHMpOgoJCWdsb2JhbCBfcmVzdWx0c2NvdW50ZXIKCQloaXRzID0gbWFwKGxhbWJkYSAocGF0aCwgaGl0cyk6IChzdWNrdGl0bGUocGF0aCksIHBhdGgsIGhpdHMpLCBoaXRzKQoJCWhpdHMuc29ydCgpCgkJc2VsZi5oaXRzID0gaGl0cwoJCW5pY2VoaXRzID0gbWFwKAoJCQkJbGFtYmRhICh0aXRsZSwgcGF0aCwgaGl0cyk6CgkJCQl0aXRsZSArICdccicgKyBzdHJpbmcuam9pbigKCQkJCW1hcChsYW1iZGEgKGMsIHApOiAiJXMgKCVkKSIgJSAocCwgYyksIGhpdHMpLCAnLCAnKSwgaGl0cykKCQluaWNlaGl0cy5zb3J0KCkKCQlzZWxmLncgPSBXLldpbmRvdygoNDQwLCAzMDApLCAiU2VhcmNoIHJlc3VsdHMgJWQiICUgX3Jlc3VsdHNjb3VudGVyLCBtaW5zaXplID0gKDIwMCwgMTAwKSkKCQlzZWxmLncucmVzdWx0cyA9IFR3b0xpbmVMaXN0KCgtMSwgLTEsIDEsIC0xNCksIG5pY2VoaXRzLCBzZWxmLmxpc3RoaXQpCgkJc2VsZi53Lm9wZW4oKQoJCXNlbGYudy5iaW5kKCdyZXR1cm4nLCBzZWxmLmxpc3RoaXQpCgkJc2VsZi53LmJpbmQoJ2VudGVyJywgc2VsZi5saXN0aGl0KQoJCV9yZXN1bHRzY291bnRlciA9IF9yZXN1bHRzY291bnRlciArIDEKCQlzZWxmLmJyb3dzZXIgPSBOb25lCgkKCWRlZiBsaXN0aGl0KHNlbGYsIGlzZGJsID0gMSk6CgkJaWYgaXNkYmw6CgkJCWZvciBpIGluIHNlbGYudy5yZXN1bHRzLmdldHNlbGVjdGlvbigpOgoJCQkJaWYgc2VsZi5icm93c2VyIGlzIE5vbmU6CgkJCQkJc2VsZi5icm93c2VyID0gV2ViQnJvd3NlcihTSUdOQVRVUkUsIHN0YXJ0ID0gMSkKCQkJCXNlbGYuYnJvd3Nlci5vcGVuZmlsZShzZWxmLmhpdHNbaV1bMV0pCgpjbGFzcyBTdGF0dXM6CgkKCWRlZiBfX2luaXRfXyhzZWxmKToKCQlzZWxmLncgPSBXLkRpYWxvZygoNDQwLCA2NCksICJTZWFyY2hpbmeKIikKCQlzZWxmLncuc2VhcmNoaW5nID0gVy5UZXh0Qm94KCg0LCA0LCAtNCwgMTYpLCAiRGV2RGV2OlB5UHlEb2MgMS41LjE6ZXh0OnBhcnNlVHVwbGVBbmRLZXl3b3Jkcy5odG1sIikKCQlzZWxmLncuaGl0cyA9IFcuVGV4dEJveCgoNCwgMjQsIC00LCAxNiksICJIaXRzOiAwIikKCQlzZWxmLncuY2FuY2VsdGlwID0gVy5UZXh0Qm94KCg0LCA0NCwgLTQsIDE2KSwgIlR5cGUgY21kLXBlcmlvZCAoLikgdG8gY2FuY2VsLiIpCgkJc2VsZi53Lm9wZW4oKQoJCglkZWYgc2V0KHNlbGYsIHBhdGgsIGhpdHMpOgoJCXNlbGYudy5zZWFyY2hpbmcuc2V0KHBhdGgpCgkJc2VsZi53LmhpdHMuc2V0KCdIaXRzOiAnICsgYGhpdHNgKQoJCWFwcC5icmVhdGhlKCkKCQoJZGVmIGNsb3NlKHNlbGYpOgoJCXNlbGYudy5jbG9zZSgpCgoKZGVmIG1hdGNoKHRleHQsIHBhdHRlcm5zLCBhbGwpOgoJaGl0cyA9IFtdCgloaXRzYXBwZW5kID0gaGl0cy5hcHBlbmQKCXN0cmluZ2NvdW50ID0gc3RyaW5nLmNvdW50Cglmb3IgcGF0IGluIHBhdHRlcm5zOgoJCWMgPSBzdHJpbmdjb3VudCh0ZXh0LCBwYXQpCgkJaWYgYyA+IDA6CgkJCWhpdHNhcHBlbmQoKGMsIHBhdCkpCgkJZWxpZiBhbGw6CgkJCWhpdHNbOl0gPSBbXQoJCQlicmVhawoJaGl0cy5zb3J0KCkKCWhpdHMucmV2ZXJzZSgpCglyZXR1cm4gaGl0cwoKZGVmIGRvc2VhcmNoKGRvY3BhdGgsIHNlYXJjaHN0cmluZywgc2V0dGluZ3MpOgoJKGRvY3BhdGgsIGtpbmQsIGNhc2UsIHdvcmQsIHR1dCwgbGliLCByZWYsIGV4dCwgYXBpKSA9IHNldHRpbmdzCglib29rcyA9IFsodHV0LCAndHV0JyksIChsaWIsICdsaWInKSwgKHJlZiwgJ3JlZicpLCAoZXh0LCAnZXh0JyksIChhcGksICdhcGknKV0KCWlmIG5vdCBjYXNlOgoJCXNlYXJjaHN0cmluZyA9IHN0cmluZy5sb3dlcihzZWFyY2hzdHJpbmcpCgkKCWlmIGtpbmQgPT0gMToKCQlwYXR0ZXJucyA9IHN0cmluZy5zcGxpdChzZWFyY2hzdHJpbmcpCgkJYWxsID0gMQoJZWxpZiBraW5kID09IDI6CgkJcGF0dGVybnMgPSBzdHJpbmcuc3BsaXQoc2VhcmNoc3RyaW5nKQoJCWFsbCA9IDAKCWVsc2U6CgkJcGF0dGVybnMgPSBbc2VhcmNoc3RyaW5nXQoJCWFsbCA9IDAgIyBub3QgcmVsZXZhbnQKCQoJb3NwYXRoam9pbiA9IG9zLnBhdGguam9pbgoJc3RyaW5nbG93ZXIgPSBzdHJpbmcubG93ZXIKCXN0YXR1cyA9IFN0YXR1cygpCglzdGF0dXNzZXQgPSBzdGF0dXMuc2V0CglfbWF0Y2ggPSBtYXRjaAoJX29wZW4gPSBvcGVuCgloaXRzID0ge30KCXRyeToKCQlNYWNPUy5FbmFibGVBcHBzd2l0Y2goMCkKCQl0cnk6CgkJCWZvciBkbywgbmFtZSBpbiBib29rczoKCQkJCWlmIG5vdCBkbzoKCQkJCQljb250aW51ZQoJCQkJYm9va3BhdGggPSBvc3BhdGhqb2luKGRvY3BhdGgsIG5hbWUpCgkJCQlpZiBub3Qgb3MucGF0aC5leGlzdHMoYm9va3BhdGgpOgoJCQkJCWNvbnRpbnVlCgkJCQlmaWxlcyA9IG9zLmxpc3RkaXIoYm9va3BhdGgpCgkJCQlmb3IgZmlsZSBpbiBmaWxlczoKCQkJCQlmdWxscGF0aCA9IG9zcGF0aGpvaW4oYm9va3BhdGgsIGZpbGUpCgkJCQkJaWYgZnVsbHBhdGhbLTU6XSA8PiAnLmh0bWwnOgoJCQkJCQljb250aW51ZQoJCQkJCXN0YXR1c3NldChmdWxscGF0aCwgbGVuKGhpdHMpKQoJCQkJCWYgPSBfb3BlbihmdWxscGF0aCkKCQkJCQl0ZXh0ID0gZi5yZWFkKCkKCQkJCQlpZiBub3QgY2FzZToKCQkJCQkJdGV4dCA9IHN0cmluZ2xvd2VyKHRleHQpCgkJCQkJZi5jbG9zZSgpCgkJCQkJZmlsZWhpdHMgPSBfbWF0Y2godGV4dCwgcGF0dGVybnMsIGFsbCkKCQkJCQlpZiBmaWxlaGl0czoKCQkJCQkJaGl0c1tmdWxscGF0aF0gPSBmaWxlaGl0cwoJCWZpbmFsbHk6CgkJCU1hY09TLkVuYWJsZUFwcHN3aXRjaCgtMSkKCQkJc3RhdHVzLmNsb3NlKCkKCWV4Y2VwdCBLZXlib2FyZEludGVycnVwdDoKCQlwYXNzCgloaXRzID0gaGl0cy5pdGVtcygpCgloaXRzLnNvcnQoKQoJcmV0dXJuIGhpdHMKCgpjbGFzcyBQeURvY1NlYXJjaDoKCQoJZGVmIF9faW5pdF9fKHNlbGYpOgoJCXByZWZzID0gTWFjUHJlZnMuR2V0UHJlZnMoVy5nZXRhcHBsaWNhdGlvbigpLnByZWZmaWxlcGF0aCkKCQl0cnk6CgkJCShkb2NwYXRoLCBraW5kLCBjYXNlLCB3b3JkLCB0dXQsIGxpYiwgcmVmLCBleHQsIGFwaSkgPSBwcmVmcy5kb2NzZWFyY2hlbmdpbmUKCQlleGNlcHQ6CgkJCShkb2NwYXRoLCBraW5kLCBjYXNlLCB3b3JkLCB0dXQsIGxpYiwgcmVmLCBleHQsIGFwaSkgPSBwcmVmcy5kb2NzZWFyY2hlbmdpbmUgPSBcCgkJCQkoIiIsIDAsIDAsIDAsIDEsIDEsIDAsIDAsIDApCgkJCgkJaWYgZG9jcGF0aCBhbmQgbm90IHZlcmlmeWRvY3BhdGgoZG9jcGF0aCk6CgkJCWRvY3BhdGggPSAiIgoJCQoJCXNlbGYudyA9IFcuV2luZG93KCg0MDAsIDIwMCksICJTZWFyY2ggdGhlIFB5dGhvbiBEb2N1bWVudGF0aW9uIikKCQlzZWxmLncuc2VhcmNodGV4dCA9IFcuRWRpdFRleHQoKDEwLCAxMCwgLTEwMCwgMjApLCBjYWxsYmFjayA9IHNlbGYuY2hlY2tidXR0b25zKQoJCXNlbGYudy5zZWFyY2hidXR0b24gPSBXLkJ1dHRvbigoLTkwLCAxMiwgODAsIDE2KSwgIlNlYXJjaCIsIHNlbGYuc2VhcmNoKQoJCWJ1dHRvbnMgPSBbXQoJCQoJCWd1dHRlciA9IDEwCgkJd2lkdGggPSAxMzAKCQlib29rc3RhcnQgPSB3aWR0aCArIDIgKiBndXR0ZXIKCQlzZWxmLncucGhyYXNlcmFkaW8gPSBXLlJhZGlvQnV0dG9uKCgxMCwgMzgsIHdpZHRoLCAxNiksICJBcyBhIHBocmFzZSIsIGJ1dHRvbnMpCgkJc2VsZi53LmFsbHdvcmRzcmFkaW8gPSBXLlJhZGlvQnV0dG9uKCgxMCwgNTgsIHdpZHRoLCAxNiksICJBbGwgd29yZHMiLCBidXR0b25zKQoJCXNlbGYudy5hbnl3b3Jkc3JhZGlvID0gVy5SYWRpb0J1dHRvbigoMTAsIDc4LCB3aWR0aCwgMTYpLCAiQW55IHdvcmQiLCBidXR0b25zKQoJCXNlbGYudy5jYXNlc2VucyA9IFcuQ2hlY2tCb3goKDEwLCA5OCwgd2lkdGgsIDE2KSwgIkNhc2Ugc2Vuc2l0aXZlIikKCQlzZWxmLncud2hvbGV3b3JkcyA9IFcuQ2hlY2tCb3goKDEwLCAxMTgsIHdpZHRoLCAxNiksICJXaG9sZSB3b3JkcyIpCgkJc2VsZi53LnR1dG9yaWFsID0gVy5DaGVja0JveCgoYm9va3N0YXJ0LCAzOCwgLTEwLCAxNiksICJUdXRvcmlhbCIpCgkJc2VsZi53LmxpYnJhcnkgPSBXLkNoZWNrQm94KChib29rc3RhcnQsIDU4LCAtMTAsIDE2KSwgIkxpYnJhcnkgcmVmZXJlbmNlIikKCQlzZWxmLncubGFuZ3VlcmVmID0gVy5DaGVja0JveCgoYm9va3N0YXJ0LCA3OCwgLTEwLCAxNiksICJMYW51YWdlIHJlZmVyZW5jZSBtYW51YWwiKQoJCXNlbGYudy5leHRlbmRpbmcgPSBXLkNoZWNrQm94KChib29rc3RhcnQsIDk4LCAtMTAsIDE2KSwgIkV4dGVuZGluZyAmIGVtYmVkZGluZyIpCgkJc2VsZi53LmFwaSA9IFcuQ2hlY2tCb3goKGJvb2tzdGFydCwgMTE4LCAtMTAsIDE2KSwgIkMvQysrIEFQSSIpCgkJCgkJc2VsZi53LnNldGRvY2ZvbGRlcmJ1dHRvbiA9IFcuQnV0dG9uKCgxMCwgLTMwLCA4MCwgMTYpLCAiU2V0IGRvYyBmb2xkZXIiLCBzZWxmLnNldGRvY3BhdGgpCgkJCgkJaWYgZG9jcGF0aDoKCQkJc2VsZi53LnNldGRlZmF1bHRidXR0b24oc2VsZi53LnNlYXJjaGJ1dHRvbikKCQllbHNlOgoJCQlzZWxmLncuc2V0ZGVmYXVsdGJ1dHRvbihzZWxmLncuc2V0ZG9jZm9sZGVyYnV0dG9uKQoJCQoJCXNlbGYuZG9jcGF0aCA9IGRvY3BhdGgKCQlpZiBub3QgZG9jcGF0aDoKCQkJZG9jcGF0aCA9ICIocGxlYXNlIHNlbGVjdCB0aGUgUHl0aG9uIGh0bWwgZG9jdW1lbnRhdGlvbiBmb2xkZXIpIgoJCXNlbGYudy5kb2Nmb2xkZXIgPSBXLlRleHRCb3goKDEwMCwgLTI4LCAtMTAsIDE2KSwgZG9jcGF0aCkKCQkKCQlbc2VsZi53LnBocmFzZXJhZGlvLCBzZWxmLncuYWxsd29yZHNyYWRpbywgc2VsZi53LmFueXdvcmRzcmFkaW9dW2tpbmRdLnNldCgxKQoJCQoJCXNlbGYudy5jYXNlc2Vucy5zZXQoY2FzZSkKCQlzZWxmLncud2hvbGV3b3Jkcy5zZXQod29yZCkKCQlzZWxmLncudHV0b3JpYWwuc2V0KHR1dCkKCQlzZWxmLncubGlicmFyeS5zZXQobGliKQoJCXNlbGYudy5sYW5ndWVyZWYuc2V0KHJlZikKCQlzZWxmLncuZXh0ZW5kaW5nLnNldChleHQpCgkJc2VsZi53LmFwaS5zZXQoYXBpKQoJCQoJCXNlbGYudy5vcGVuKCkKCQlzZWxmLncud2hvbGV3b3Jkcy5lbmFibGUoMCkKCQlzZWxmLncuYmluZCgnPGNsb3NlPicsIHNlbGYuY2xvc2UpCgkJc2VsZi53LnNlYXJjaGJ1dHRvbi5lbmFibGUoMCkKCQoJZGVmIHNlYXJjaChzZWxmKToKCQloaXRzID0gZG9zZWFyY2goc2VsZi5kb2NwYXRoLCBzZWxmLncuc2VhcmNodGV4dC5nZXQoKSwgc2VsZi5nZXRzZXR0aW5ncygpKQoJCWlmIGhpdHM6CgkJCVJlc3VsdHMoaGl0cykKCQllbGlmIGhhc2F0dHIoTWFjT1MsICdTeXNCZWVwJyk6CgkJCU1hY09TLlN5c0JlZXAoMCkKCQkjaW1wb3J0IFB5QnJvd3NlcgoJCSNQeUJyb3dzZXIuQnJvd3NlcihoaXRzKQoJCglkZWYgc2V0ZG9jcGF0aChzZWxmKToKCQlmc3MsIG9rID0gbWFjZnMuR2V0RGlyZWN0b3J5KCkKCQlpZiBvazoKCQkJZG9jcGF0aCA9IGZzcy5hc19wYXRobmFtZSgpCgkJCWlmIG5vdCB2ZXJpZnlkb2NwYXRoKGRvY3BhdGgpOgoJCQkJVy5NZXNzYWdlKCJUaGlzIGRvZXMgbm90IHNlZW0gdG8gYmUgYSBQeXRob24gZG9jdW1lbnRhdGlvbiBmb2xkZXIuLi4iKQoJCQllbHNlOgoJCQkJc2VsZi5kb2NwYXRoID0gZG9jcGF0aAoJCQkJc2VsZi53LmRvY2ZvbGRlci5zZXQoZG9jcGF0aCkKCQkJCXNlbGYudy5zZXRkZWZhdWx0YnV0dG9uKHNlbGYudy5zZWFyY2hidXR0b24pCgkKCWRlZiBjbG9zZShzZWxmKToKCQlwcmVmcyA9IE1hY1ByZWZzLkdldFByZWZzKFcuZ2V0YXBwbGljYXRpb24oKS5wcmVmZmlsZXBhdGgpCgkJcHJlZnMuZG9jc2VhcmNoZW5naW5lID0gc2VsZi5nZXRzZXR0aW5ncygpCgkKCWRlZiBnZXRzZXR0aW5ncyhzZWxmKToKCQlyYWRpb2J1dHRvbnMgPSBbc2VsZi53LnBocmFzZXJhZGlvLCBzZWxmLncuYWxsd29yZHNyYWRpbywgc2VsZi53LmFueXdvcmRzcmFkaW9dCgkJZm9yIGkgaW4gcmFuZ2UoMyk6CgkJCWlmIHJhZGlvYnV0dG9uc1tpXS5nZXQoKToKCQkJCWtpbmQgPSBpCgkJCQlicmVhawoJCWRvY3BhdGggPSBzZWxmLmRvY3BhdGgKCQljYXNlID0gc2VsZi53LmNhc2VzZW5zLmdldCgpCgkJd29yZCA9IHNlbGYudy53aG9sZXdvcmRzLmdldCgpCgkJdHV0ID0gc2VsZi53LnR1dG9yaWFsLmdldCgpCgkJbGliID0gc2VsZi53LmxpYnJhcnkuZ2V0KCkKCQlyZWYgPSBzZWxmLncubGFuZ3VlcmVmLmdldCgpCgkJZXh0ID0gc2VsZi53LmV4dGVuZGluZy5nZXQoKQoJCWFwaSA9IHNlbGYudy5hcGkuZ2V0KCkKCQlyZXR1cm4gKGRvY3BhdGgsIGtpbmQsIGNhc2UsIHdvcmQsIHR1dCwgbGliLCByZWYsIGV4dCwgYXBpKQoJCglkZWYgY2hlY2tidXR0b25zKHNlbGYpOgoJCXNlbGYudy5zZWFyY2hidXR0b24uZW5hYmxlKG5vdCBub3Qgc2VsZi53LnNlYXJjaHRleHQuZ2V0KCkpCg==