IiIiIEEgU0FYMiBkcml2ZXIgZm9yIGxpYnhtbDIsIG9uIHRvcCBvZiBpdCdzIFhtbFJlYWRlciBBUEkKClVTQUdFCiAgICAjIHB1dCB0aGlzIGZpbGUgKGRydl9saWJ4bWwyLnB5KSBpbiBQWVRIT05QQVRICiAgICBpbXBvcnQgeG1sLnNheAogICAgcmVhZGVyID0geG1sLnNheC5tYWtlX3BhcnNlcihbImRydl9saWJ4bWwyIl0pCiAgICAjIC4uLmFuZCB0aGUgcmVzdCBpcyBzdGFuZGFyZCBweXRob24gc2F4LgoKQ0FWRUFUUwogICAgLSBMZXhpY2FsIGhhbmRsZXJzIGFyZSBzdXBwb3J0ZWQsIGV4Y2VwdCBmb3Igc3RhcnQvZW5kRW50aXR5CiAgICAgICh3YWl0aW5nIGZvciBYbWxSZWFkZXIuUmVzb2x2ZUVudGl0eSkgYW5kIHN0YXJ0L2VuZERURAogICAgLSBFcnJvciBjYWxsYmFja3MgYXJlIG5vdCBleGFjdGx5IHN5bmNocm9ub3VzLCB0aGV5IHRlbmQKICAgICAgdG8gYmUgaW52b2tlZCBiZWZvcmUgdGhlIGNvcnJlc3BvbmRpbmcgY29udGVudCBjYWxsYmFjaywKICAgICAgYmVjYXVzZSB0aGUgdW5kZXJseWluZyByZWFkZXIgaW50ZXJmYWNlIHBhcnNlcwogICAgICBkYXRhIGJ5IGNodW5rcyBvZiA1MTIgYnl0ZXMKICAgIApUT0RPCiAgICAtIHNlYXJjaCBmb3IgVE9ETwogICAgLSBzb21lIEVycm9ySGFuZGxlciBldmVudHMgKHdhcm5pbmcpCiAgICAtIHNvbWUgQ29udGVudEhhbmRsZXIgZXZlbnRzIChzZXREb2N1bWVudExvY2F0b3IsIHNraXBwZWRFbnRpdHkpCiAgICAtIEVudGl0eVJlc29sdmVyICh1c2luZyBsaWJ4bWwyLj8pCiAgICAtIERUREhhbmRsZXIgKGlmL3doZW4gbGlieG1sMiBleHBvc2VzIHN1Y2ggbm9kZSB0eXBlcykKICAgIC0gRGVjbEhhbmRsZXIgKGlmL3doZW4gbGlieG1sMiBleHBvc2VzIHN1Y2ggbm9kZSB0eXBlcykKICAgIC0gcHJvcGVydHlfeG1sX3N0cmluZz8KICAgIC0gZmVhdHVyZV9zdHJpbmdfaW50ZXJuaW5nPwogICAgLSBJbmNyZW1lbnRhbCBwYXJzZXIKICAgIC0gYWRkaXRpb25hbCBwZXJmb3JtYW5jZSB0dW5pbmc6CiAgICAgIC0gb25lIG1pZ2h0IGNhY2hlIGNhbGxiYWNrcyB0byBhdm9pZCBzb21lIG5hbWUgbG9va3VwcwogICAgICAtIG9uZSBtaWdodCBpbXBsZW1lbnQgYSBzbWFydGVyIHdheSB0byBwYXNzIGF0dHJpYnV0ZXMgdG8gc3RhcnRFbGVtZW50CiAgICAgICAgKHNvbWUga2luZCBvZiBsYXp5IGV2YWx1YXRpb24/KQogICAgICAtIHRoZXJlIG1pZ2h0IGJlIHJvb20gZm9yIGltcHJvdmVtZW50IGluIHN0YXJ0L2VuZFByZWZpeE1hcHBpbmcKICAgICAgLSBvdGhlcj8KCiIiIgoKX19hdXRob3JfXyAgPSB1IlN06XBoYW5lIEJpZG91bCA8c2JpQHNreW5ldC5iZT4iCl9fdmVyc2lvbl9fID0gIjAuMyIKCmltcG9ydCBjb2RlY3MKaW1wb3J0IHN5cwpmcm9tIHR5cGVzIGltcG9ydCBTdHJpbmdUeXBlLCBVbmljb2RlVHlwZQpTdHJpbmdUeXBlcyA9IChTdHJpbmdUeXBlLFVuaWNvZGVUeXBlKQoKZnJvbSB4bWwuc2F4Ll9leGNlcHRpb25zIGltcG9ydCAqCmZyb20geG1sLnNheCBpbXBvcnQgeG1scmVhZGVyLCBzYXh1dGlscwpmcm9tIHhtbC5zYXguaGFuZGxlciBpbXBvcnQgXAogICAgIGZlYXR1cmVfbmFtZXNwYWNlcywgXAogICAgIGZlYXR1cmVfbmFtZXNwYWNlX3ByZWZpeGVzLCBcCiAgICAgZmVhdHVyZV9zdHJpbmdfaW50ZXJuaW5nLCBcCiAgICAgZmVhdHVyZV92YWxpZGF0aW9uLCBcCiAgICAgZmVhdHVyZV9leHRlcm5hbF9nZXMsIFwKICAgICBmZWF0dXJlX2V4dGVybmFsX3BlcywgXAogICAgIHByb3BlcnR5X2xleGljYWxfaGFuZGxlciwgXAogICAgIHByb3BlcnR5X2RlY2xhcmF0aW9uX2hhbmRsZXIsIFwKICAgICBwcm9wZXJ0eV9kb21fbm9kZSwgXAogICAgIHByb3BlcnR5X3htbF9zdHJpbmcKCiMgbGlieG1sMiByZXR1cm5zIHN0cmluZ3MgYXMgVVRGOApfZGVjb2RlciA9IGNvZGVjcy5sb29rdXAoInV0ZjgiKVsxXQpkZWYgX2Qocyk6CiAgICBpZiBzIGlzIE5vbmU6CiAgICAgICAgcmV0dXJuIHMKICAgIGVsc2U6CiAgICAgICAgcmV0dXJuIF9kZWNvZGVyKHMpWzBdCgp0cnk6CiAgICBpbXBvcnQgbGlieG1sMgpleGNlcHQgSW1wb3J0RXJyb3IsIGU6CiAgICByYWlzZSBTQVhSZWFkZXJOb3RBdmFpbGFibGUoImxpYnhtbDIgbm90IGF2YWlsYWJsZTogIiBcCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImltcG9ydCBlcnJvciB3YXM6ICVzIiAlIGUpCgpjbGFzcyBMb2NhdG9yKHhtbHJlYWRlci5Mb2NhdG9yKToKICAgICIiIlNBWCBMb2NhdG9yIGFkYXB0ZXIgZm9yIGxpYnhtbDIueG1sVGV4dFJlYWRlckxvY2F0b3IiIiIKCiAgICBkZWYgX19pbml0X18oc2VsZixsb2NhdG9yKToKICAgICAgICBzZWxmLl9fbG9jYXRvciA9IGxvY2F0b3IKCiAgICBkZWYgZ2V0Q29sdW1uTnVtYmVyKHNlbGYpOgogICAgICAgICJSZXR1cm4gdGhlIGNvbHVtbiBudW1iZXIgd2hlcmUgdGhlIGN1cnJlbnQgZXZlbnQgZW5kcy4iCiAgICAgICAgcmV0dXJuIC0xCgogICAgZGVmIGdldExpbmVOdW1iZXIoc2VsZik6CiAgICAgICAgIlJldHVybiB0aGUgbGluZSBudW1iZXIgd2hlcmUgdGhlIGN1cnJlbnQgZXZlbnQgZW5kcy4iCiAgICAgICAgcmV0dXJuIHNlbGYuX19sb2NhdG9yLkxpbmVOdW1iZXIoKQoKICAgIGRlZiBnZXRQdWJsaWNJZChzZWxmKToKICAgICAgICAiUmV0dXJuIHRoZSBwdWJsaWMgaWRlbnRpZmllciBmb3IgdGhlIGN1cnJlbnQgZXZlbnQuIgogICAgICAgIHJldHVybiBOb25lCgogICAgZGVmIGdldFN5c3RlbUlkKHNlbGYpOgogICAgICAgICJSZXR1cm4gdGhlIHN5c3RlbSBpZGVudGlmaWVyIGZvciB0aGUgY3VycmVudCBldmVudC4iCiAgICAgICAgcmV0dXJuIHNlbGYuX19sb2NhdG9yLkJhc2VVUkkoKQoKY2xhc3MgTGliWG1sMlJlYWRlcih4bWxyZWFkZXIuWE1MUmVhZGVyKToKCiAgICBkZWYgX19pbml0X18oc2VsZik6CiAgICAgICAgeG1scmVhZGVyLlhNTFJlYWRlci5fX2luaXRfXyhzZWxmKQogICAgICAgICMgZmVhdHVyZXMKICAgICAgICBzZWxmLl9fbnMgPSAwCiAgICAgICAgc2VsZi5fX25zcGZ4ID0gMAogICAgICAgIHNlbGYuX192YWxpZGF0ZSA9IDAKICAgICAgICAjIHBhcnNpbmcgZmxhZwogICAgICAgIHNlbGYuX19wYXJzaW5nID0gMAogICAgICAgICMgYWRkaXRpb25hbCBoYW5kbGVycwogICAgICAgIHNlbGYuX19sZXhfaGFuZGxlciA9IE5vbmUKICAgICAgICBzZWxmLl9fZGVjbF9oYW5kbGVyID0gTm9uZQogICAgICAgICMgZXJyb3IgbWVzc2FnZXMgYWNjdW11bGF0b3IKICAgICAgICBzZWxmLl9fZXJyb3JzID0gTm9uZQoKICAgIGRlZiBfZXJyb3JIYW5kbGVyKHNlbGYsYXJnLG1zZyxzZXZlcml0eSxsb2NhdG9yKToKICAgICAgICBpZiBzZWxmLl9fZXJyb3JzIGlzIE5vbmU6CiAgICAgICAgICAgIHNlbGYuX19lcnJvcnMgPSBbXQogICAgICAgIHNlbGYuX19lcnJvcnMuYXBwZW5kKChzZXZlcml0eSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgU0FYUGFyc2VFeGNlcHRpb24obXNnLE5vbmUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIExvY2F0b3IobG9jYXRvcikpKSkKCiAgICBkZWYgX3JlcG9ydEVycm9ycyhzZWxmLGZhdGFsKToKICAgICAgICBmb3Igc2V2ZXJpdHksZXhjZXB0aW9uIGluIHNlbGYuX19lcnJvcnM6CiAgICAgICAgICAgIGlmIHNldmVyaXR5IGluIChsaWJ4bWwyLlBBUlNFUl9TRVZFUklUWV9WQUxJRElUWV9XQVJOSU5HLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlieG1sMi5QQVJTRVJfU0VWRVJJVFlfV0FSTklORyk6CiAgICAgICAgICAgICAgICBzZWxmLl9lcnJfaGFuZGxlci53YXJuaW5nKGV4Y2VwdGlvbikKICAgICAgICAgICAgZWxzZToKICAgICAgICAgICAgICAgICMgd2hlbiBmYXRhbCBpcyBzZXQsIHRoZSBwYXJzZSB3aWxsIHN0b3A7CiAgICAgICAgICAgICAgICAjIHdlIGNvbnNpZGVyIHRoYXQgdGhlIGxhc3QgZXJyb3IgcmVwb3J0ZWQKICAgICAgICAgICAgICAgICMgaXMgdGhlIGZhdGFsIG9uZS4KICAgICAgICAgICAgICAgIGlmIGZhdGFsIGFuZCBleGNlcHRpb24gaXMgc2VsZi5fX2Vycm9yc1stMV1bMV06CiAgICAgICAgICAgICAgICAgICAgc2VsZi5fZXJyX2hhbmRsZXIuZmF0YWxFcnJvcihleGNlcHRpb24pCiAgICAgICAgICAgICAgICBlbHNlOgogICAgICAgICAgICAgICAgICAgIHNlbGYuX2Vycl9oYW5kbGVyLmVycm9yKGV4Y2VwdGlvbikKICAgICAgICBzZWxmLl9fZXJyb3JzID0gTm9uZQoKICAgIGRlZiBwYXJzZShzZWxmLCBzb3VyY2UpOgogICAgICAgIHNlbGYuX19wYXJzaW5nID0gMQogICAgICAgIHRyeToKICAgICAgICAgICAgIyBwcmVwYXJlIHNvdXJjZSBhbmQgY3JlYXRlIHJlYWRlcgogICAgICAgICAgICBpZiB0eXBlKHNvdXJjZSkgaW4gU3RyaW5nVHlwZXM6CiAgICAgICAgICAgICAgICByZWFkZXIgPSBsaWJ4bWwyLm5ld1RleHRSZWFkZXJGaWxlbmFtZShzb3VyY2UpCiAgICAgICAgICAgIGVsc2U6CiAgICAgICAgICAgICAgICBzb3VyY2UgPSBzYXh1dGlscy5wcmVwYXJlX2lucHV0X3NvdXJjZShzb3VyY2UpCiAgICAgICAgICAgICAgICBpbnB1dCA9IGxpYnhtbDIuaW5wdXRCdWZmZXIoc291cmNlLmdldEJ5dGVTdHJlYW0oKSkKICAgICAgICAgICAgICAgIHJlYWRlciA9IGlucHV0Lm5ld1RleHRSZWFkZXIoc291cmNlLmdldFN5c3RlbUlkKCkpCiAgICAgICAgICAgIHJlYWRlci5TZXRFcnJvckhhbmRsZXIoc2VsZi5fZXJyb3JIYW5kbGVyLE5vbmUpCiAgICAgICAgICAgICMgY29uZmlndXJlIHJlYWRlcgogICAgICAgICAgICByZWFkZXIuU2V0UGFyc2VyUHJvcChsaWJ4bWwyLlBBUlNFUl9MT0FERFRELDEpCiAgICAgICAgICAgIHJlYWRlci5TZXRQYXJzZXJQcm9wKGxpYnhtbDIuUEFSU0VSX0RFRkFVTFRBVFRSUywxKQogICAgICAgICAgICByZWFkZXIuU2V0UGFyc2VyUHJvcChsaWJ4bWwyLlBBUlNFUl9TVUJTVF9FTlRJVElFUywxKQogICAgICAgICAgICByZWFkZXIuU2V0UGFyc2VyUHJvcChsaWJ4bWwyLlBBUlNFUl9WQUxJREFURSxzZWxmLl9fdmFsaWRhdGUpCiAgICAgICAgICAgICMgd2UgcmV1c2UgYXR0cmlidXRlIG1hcHMgKGZvciBhIHNsaWdodCBwZXJmb3JtYW5jZSBnYWluKQogICAgICAgICAgICBpZiBzZWxmLl9fbnM6CiAgICAgICAgICAgICAgICBhdHRyaWJ1dGVzTlNJbXBsID0geG1scmVhZGVyLkF0dHJpYnV0ZXNOU0ltcGwoe30se30pCiAgICAgICAgICAgIGVsc2U6CiAgICAgICAgICAgICAgICBhdHRyaWJ1dGVzSW1wbCA9IHhtbHJlYWRlci5BdHRyaWJ1dGVzSW1wbCh7fSkKICAgICAgICAgICAgIyBwcmVmaXhlcyB0byBwb3AgKGZvciBlbmRQcmVmaXhNYXBwaW5nKQogICAgICAgICAgICBwcmVmaXhlcyA9IFtdCiAgICAgICAgICAgICMgc3RhcnQgbG9vcAogICAgICAgICAgICBzZWxmLl9jb250X2hhbmRsZXIuc3RhcnREb2N1bWVudCgpCiAgICAgICAgICAgIHdoaWxlIDE6CiAgICAgICAgICAgICAgICByID0gcmVhZGVyLlJlYWQoKQogICAgICAgICAgICAgICAgIyBjaGVjayBmb3IgZXJyb3JzCiAgICAgICAgICAgICAgICBpZiByID09IDE6CiAgICAgICAgICAgICAgICAgICAgaWYgbm90IHNlbGYuX19lcnJvcnMgaXMgTm9uZToKICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5fcmVwb3J0RXJyb3JzKDApCiAgICAgICAgICAgICAgICBlbGlmIHIgPT0gMDoKICAgICAgICAgICAgICAgICAgICBpZiBub3Qgc2VsZi5fX2Vycm9ycyBpcyBOb25lOgogICAgICAgICAgICAgICAgICAgICAgICBzZWxmLl9yZXBvcnRFcnJvcnMoMCkKICAgICAgICAgICAgICAgICAgICBicmVhayAjIGVuZCBvZiBwYXJzZQogICAgICAgICAgICAgICAgZWxzZToKICAgICAgICAgICAgICAgICAgICBpZiBub3Qgc2VsZi5fX2Vycm9ycyBpcyBOb25lOgogICAgICAgICAgICAgICAgICAgICAgICBzZWxmLl9yZXBvcnRFcnJvcnMoMSkKICAgICAgICAgICAgICAgICAgICBlbHNlOgogICAgICAgICAgICAgICAgICAgICAgICBzZWxmLl9lcnJfaGFuZGxlci5mYXRhbEVycm9yKFwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFNBWEV4Y2VwdGlvbigiUmVhZCBmYWlsZWQgKG5vIGRldGFpbHMgYXZhaWxhYmxlKSIpKQogICAgICAgICAgICAgICAgICAgIGJyZWFrICMgZmF0YWwgcGFyc2UgZXJyb3IKICAgICAgICAgICAgICAgICMgZ2V0IG5vZGUgdHlwZQogICAgICAgICAgICAgICAgbm9kZVR5cGUgPSByZWFkZXIuTm9kZVR5cGUoKQogICAgICAgICAgICAgICAgIyBFbGVtZW50CiAgICAgICAgICAgICAgICBpZiBub2RlVHlwZSA9PSAxOiAKICAgICAgICAgICAgICAgICAgICBpZiBzZWxmLl9fbnM6CiAgICAgICAgICAgICAgICAgICAgICAgIGVsdE5hbWUgPSAoX2QocmVhZGVyLk5hbWVzcGFjZVVyaSgpKSxcCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgX2QocmVhZGVyLkxvY2FsTmFtZSgpKSkKICAgICAgICAgICAgICAgICAgICAgICAgZWx0UU5hbWUgPSBfZChyZWFkZXIuTmFtZSgpKQogICAgICAgICAgICAgICAgICAgICAgICBhdHRyaWJ1dGVzTlNJbXBsLl9hdHRycyA9IGF0dHJzID0ge30KICAgICAgICAgICAgICAgICAgICAgICAgYXR0cmlidXRlc05TSW1wbC5fcW5hbWVzID0gcW5hbWVzID0ge30KICAgICAgICAgICAgICAgICAgICAgICAgbmV3UHJlZml4ZXMgPSBbXQogICAgICAgICAgICAgICAgICAgICAgICB3aGlsZSByZWFkZXIuTW92ZVRvTmV4dEF0dHJpYnV0ZSgpOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgcW5hbWUgPSBfZChyZWFkZXIuTmFtZSgpKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUgPSBfZChyZWFkZXIuVmFsdWUoKSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIHFuYW1lLnN0YXJ0c3dpdGgoInhtbG5zIik6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgbGVuKHFuYW1lKSA+IDU6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld1ByZWZpeCA9IHFuYW1lWzY6XQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsc2U6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld1ByZWZpeCA9IE5vbmUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdQcmVmaXhlcy5hcHBlbmQobmV3UHJlZml4KQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX2NvbnRfaGFuZGxlci5zdGFydFByZWZpeE1hcHBpbmcoXAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdQcmVmaXgsdmFsdWUpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgbm90IHNlbGYuX19uc3BmeDoKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWUgIyBkb24ndCByZXBvcnQgeG1sbnMgYXR0cmlidXRlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhdHROYW1lID0gKF9kKHJlYWRlci5OYW1lc3BhY2VVcmkoKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIF9kKHJlYWRlci5Mb2NhbE5hbWUoKSkpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBxbmFtZXNbYXR0TmFtZV0gPSBxbmFtZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgYXR0cnNbYXR0TmFtZV0gPSB2YWx1ZQogICAgICAgICAgICAgICAgICAgICAgICByZWFkZXIuTW92ZVRvRWxlbWVudCgpCiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX2NvbnRfaGFuZGxlci5zdGFydEVsZW1lbnROUyggXAogICAgICAgICAgICAgICAgICAgICAgICAgICAgZWx0TmFtZSxlbHRRTmFtZSxhdHRyaWJ1dGVzTlNJbXBsKSAKICAgICAgICAgICAgICAgICAgICAgICAgaWYgcmVhZGVyLklzRW1wdHlFbGVtZW50KCk6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxmLl9jb250X2hhbmRsZXIuZW5kRWxlbWVudE5TKGVsdE5hbWUsZWx0UU5hbWUpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgbmV3UHJlZml4IGluIG5ld1ByZWZpeGVzOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX2NvbnRfaGFuZGxlci5lbmRQcmVmaXhNYXBwaW5nKG5ld1ByZWZpeCkKICAgICAgICAgICAgICAgICAgICAgICAgZWxzZToKICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByZWZpeGVzLmFwcGVuZChuZXdQcmVmaXhlcykKICAgICAgICAgICAgICAgICAgICBlbHNlOgogICAgICAgICAgICAgICAgICAgICAgICBlbHROYW1lID0gX2QocmVhZGVyLk5hbWUoKSkKICAgICAgICAgICAgICAgICAgICAgICAgYXR0cmlidXRlc0ltcGwuX2F0dHJzID0gYXR0cnMgPSB7fQogICAgICAgICAgICAgICAgICAgICAgICB3aGlsZSByZWFkZXIuTW92ZVRvTmV4dEF0dHJpYnV0ZSgpOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgYXR0TmFtZSA9IF9kKHJlYWRlci5OYW1lKCkpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhdHRyc1thdHROYW1lXSA9IF9kKHJlYWRlci5WYWx1ZSgpKQogICAgICAgICAgICAgICAgICAgICAgICByZWFkZXIuTW92ZVRvRWxlbWVudCgpCiAgICAgICAgICAgICAgICAgICAgICAgIHNlbGYuX2NvbnRfaGFuZGxlci5zdGFydEVsZW1lbnQoIFwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVsdE5hbWUsYXR0cmlidXRlc0ltcGwpCiAgICAgICAgICAgICAgICAgICAgICAgIGlmIHJlYWRlci5Jc0VtcHR5RWxlbWVudCgpOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5fY29udF9oYW5kbGVyLmVuZEVsZW1lbnQoZWx0TmFtZSkKICAgICAgICAgICAgICAgICMgRW5kRWxlbWVudAogICAgICAgICAgICAgICAgZWxpZiBub2RlVHlwZSA9PSAxNTogCiAgICAgICAgICAgICAgICAgICAgaWYgc2VsZi5fX25zOgogICAgICAgICAgICAgICAgICAgICAgICBzZWxmLl9jb250X2hhbmRsZXIuZW5kRWxlbWVudE5TKCBcCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKF9kKHJlYWRlci5OYW1lc3BhY2VVcmkoKSksX2QocmVhZGVyLkxvY2FsTmFtZSgpKSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgX2QocmVhZGVyLk5hbWUoKSkpCiAgICAgICAgICAgICAgICAgICAgICAgIGZvciBwcmVmaXggaW4gcHJlZml4ZXMucG9wKCk6CiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxmLl9jb250X2hhbmRsZXIuZW5kUHJlZml4TWFwcGluZyhwcmVmaXgpCiAgICAgICAgICAgICAgICAgICAgZWxzZToKICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5fY29udF9oYW5kbGVyLmVuZEVsZW1lbnQoX2QocmVhZGVyLk5hbWUoKSkpCiAgICAgICAgICAgICAgICAjIFRleHQKICAgICAgICAgICAgICAgIGVsaWYgbm9kZVR5cGUgPT0gMzogCiAgICAgICAgICAgICAgICAgICAgc2VsZi5fY29udF9oYW5kbGVyLmNoYXJhY3RlcnMoX2QocmVhZGVyLlZhbHVlKCkpKQogICAgICAgICAgICAgICAgIyBXaGl0ZXNwYWNlCiAgICAgICAgICAgICAgICBlbGlmIG5vZGVUeXBlID09IDEzOiAKICAgICAgICAgICAgICAgICAgICBzZWxmLl9jb250X2hhbmRsZXIuaWdub3JhYmxlV2hpdGVzcGFjZShfZChyZWFkZXIuVmFsdWUoKSkpCiAgICAgICAgICAgICAgICAjIFNpZ25pZmljYW50V2hpdGVzcGFjZQogICAgICAgICAgICAgICAgZWxpZiBub2RlVHlwZSA9PSAxNDoKICAgICAgICAgICAgICAgICAgICBzZWxmLl9jb250X2hhbmRsZXIuY2hhcmFjdGVycyhfZChyZWFkZXIuVmFsdWUoKSkpCiAgICAgICAgICAgICAgICAjIENEQVRBCiAgICAgICAgICAgICAgICBlbGlmIG5vZGVUeXBlID09IDQ6CiAgICAgICAgICAgICAgICAgICAgaWYgbm90IHNlbGYuX19sZXhfaGFuZGxlciBpcyBOb25lOgogICAgICAgICAgICAgICAgICAgICAgICBzZWxmLl9fbGV4X2hhbmRsZXIuc3RhcnRDREFUQSgpCiAgICAgICAgICAgICAgICAgICAgc2VsZi5fY29udF9oYW5kbGVyLmNoYXJhY3RlcnMoX2QocmVhZGVyLlZhbHVlKCkpKQogICAgICAgICAgICAgICAgICAgIGlmIG5vdCBzZWxmLl9fbGV4X2hhbmRsZXIgaXMgTm9uZToKICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5fX2xleF9oYW5kbGVyLmVuZENEQVRBKCkKICAgICAgICAgICAgICAgICMgRW50aXR5UmVmZXJlbmNlCiAgICAgICAgICAgICAgICBlbGlmIG5vZGVUeXBlID09IDU6CiAgICAgICAgICAgICAgICAgICAgaWYgbm90IHNlbGYuX19sZXhfaGFuZGxlciBpcyBOb25lOgogICAgICAgICAgICAgICAgICAgICAgICBzZWxmLnN0YXJ0RW50aXR5KF9kKHJlYWRlci5OYW1lKCkpKQogICAgICAgICAgICAgICAgICAgIHJlYWRlci5SZXNvbHZlRW50aXR5KCkKICAgICAgICAgICAgICAgICMgRW5kRW50aXR5CiAgICAgICAgICAgICAgICBlbGlmIG5vZGVUeXBlID09IDE2OgogICAgICAgICAgICAgICAgICAgIGlmIG5vdCBzZWxmLl9fbGV4X2hhbmRsZXIgaXMgTm9uZToKICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5lbmRFbnRpdHkoX2QocmVhZGVyLk5hbWUoKSkpCiAgICAgICAgICAgICAgICAjIFByb2Nlc3NpbmdJbnN0cnVjdGlvbgogICAgICAgICAgICAgICAgZWxpZiBub2RlVHlwZSA9PSA3OiAKICAgICAgICAgICAgICAgICAgICBzZWxmLl9jb250X2hhbmRsZXIucHJvY2Vzc2luZ0luc3RydWN0aW9uKCBcCiAgICAgICAgICAgICAgICAgICAgICAgIF9kKHJlYWRlci5OYW1lKCkpLF9kKHJlYWRlci5WYWx1ZSgpKSkKICAgICAgICAgICAgICAgICMgQ29tbWVudAogICAgICAgICAgICAgICAgZWxpZiBub2RlVHlwZSA9PSA4OgogICAgICAgICAgICAgICAgICAgIGlmIG5vdCBzZWxmLl9fbGV4X2hhbmRsZXIgaXMgTm9uZToKICAgICAgICAgICAgICAgICAgICAgICAgc2VsZi5fX2xleF9oYW5kbGVyLmNvbW1lbnQoX2QocmVhZGVyLlZhbHVlKCkpKQogICAgICAgICAgICAgICAgIyBEb2N1bWVudFR5cGUKICAgICAgICAgICAgICAgIGVsaWYgbm9kZVR5cGUgPT0gMTA6CiAgICAgICAgICAgICAgICAgICAgI2lmIG5vdCBzZWxmLl9fbGV4X2hhbmRsZXIgaXMgTm9uZToKICAgICAgICAgICAgICAgICAgICAjICAgIHNlbGYuX19sZXhfaGFuZGxlci5zdGFydERURCgpCiAgICAgICAgICAgICAgICAgICAgcGFzcyAjIFRPRE8gKGhvdyB0byBkZXRlY3QgZW5kRFREPyBvbiBmaXJzdCBub24tZHRkIGV2ZW50PykKICAgICAgICAgICAgICAgICMgWG1sRGVjbGFyYXRpb24KICAgICAgICAgICAgICAgIGVsaWYgbm9kZVR5cGUgPT0gMTc6CiAgICAgICAgICAgICAgICAgICAgcGFzcyAjIFRPRE8KICAgICAgICAgICAgICAgICMgRW50aXR5CiAgICAgICAgICAgICAgICBlbGlmIG5vZGVUeXBlID09IDY6CiAgICAgICAgICAgICAgICAgICAgcGFzcyAjIFRPRE8gKGVudGl0eSBkZWNsKQogICAgICAgICAgICAgICAgIyBOb3RhdGlvbiAoZGVjbCkKICAgICAgICAgICAgICAgIGVsaWYgbm9kZVR5cGUgPT0gMTI6CiAgICAgICAgICAgICAgICAgICAgcGFzcyAjIFRPRE8KICAgICAgICAgICAgICAgICMgQXR0cmlidXRlIChuZXZlciBpbiB0aGlzIGxvb3ApCiAgICAgICAgICAgICAgICAjZWxpZiBub2RlVHlwZSA9PSAyOiAKICAgICAgICAgICAgICAgICMgICAgcGFzcwogICAgICAgICAgICAgICAgIyBEb2N1bWVudCAobm90IGV4cG9zZWQpCiAgICAgICAgICAgICAgICAjZWxpZiBub2RlVHlwZSA9PSA5OiAKICAgICAgICAgICAgICAgICMgICAgcGFzcwogICAgICAgICAgICAgICAgIyBEb2N1bWVudEZyYWdtZW50IChuZXZlciByZXR1cm5lZCBieSBYbWxSZWFkZXIpCiAgICAgICAgICAgICAgICAjZWxpZiBub2RlVHlwZSA9PSAxMToKICAgICAgICAgICAgICAgICMgICAgcGFzcwogICAgICAgICAgICAgICAgIyBOb25lCiAgICAgICAgICAgICAgICAjZWxpZiBub2RlVHlwZSA9PSAwOgogICAgICAgICAgICAgICAgIyAgICBwYXNzCiAgICAgICAgICAgICAgICAjIC0KICAgICAgICAgICAgICAgIGVsc2U6CiAgICAgICAgICAgICAgICAgICAgcmFpc2UgU0FYRXhjZXB0aW9uKCJVbmV4cGVjdGVkIG5vZGUgdHlwZSAlZCIgJSBub2RlVHlwZSkKICAgICAgICAgICAgaWYgciA9PSAwOgogICAgICAgICAgICAgICAgc2VsZi5fY29udF9oYW5kbGVyLmVuZERvY3VtZW50KCkKICAgICAgICAgICAgcmVhZGVyLkNsb3NlKCkKICAgICAgICBmaW5hbGx5OgogICAgICAgICAgICBzZWxmLl9fcGFyc2luZyA9IDAKCiAgICBkZWYgc2V0RFRESGFuZGxlcihzZWxmLCBoYW5kbGVyKToKICAgICAgICAjIFRPRE8gKHdoZW4gc3VwcG9ydGVkLCB0aGUgaW5oZXJpdGVkIG1ldGhvZCB3b3JrcyBqdXN0IGZpbmUpCiAgICAgICAgcmFpc2UgU0FYTm90U3VwcG9ydGVkRXhjZXB0aW9uKCJEVERIYW5kbGVyIG5vdCBzdXBwb3J0ZWQiKQoKICAgIGRlZiBzZXRFbnRpdHlSZXNvbHZlcihzZWxmLCByZXNvbHZlcik6CiAgICAgICAgIyBUT0RPICh3aGVuIHN1cHBvcnRlZCwgdGhlIGluaGVyaXRlZCBtZXRob2Qgd29ya3MganVzdCBmaW5lKQogICAgICAgIHJhaXNlIFNBWE5vdFN1cHBvcnRlZEV4Y2VwdGlvbigiRW50aXR5UmVzb2x2ZXIgbm90IHN1cHBvcnRlZCIpCgogICAgZGVmIGdldEZlYXR1cmUoc2VsZiwgbmFtZSk6CiAgICAgICAgaWYgbmFtZSA9PSBmZWF0dXJlX25hbWVzcGFjZXM6CiAgICAgICAgICAgIHJldHVybiBzZWxmLl9fbnMKICAgICAgICBlbGlmIG5hbWUgPT0gZmVhdHVyZV9uYW1lc3BhY2VfcHJlZml4ZXM6CiAgICAgICAgICAgIHJldHVybiBzZWxmLl9fbnNwZngKICAgICAgICBlbGlmIG5hbWUgPT0gZmVhdHVyZV92YWxpZGF0aW9uOgogICAgICAgICAgICByZXR1cm4gc2VsZi5fX3ZhbGlkYXRlCiAgICAgICAgZWxpZiBuYW1lID09IGZlYXR1cmVfZXh0ZXJuYWxfZ2VzOgogICAgICAgICAgICByZXR1cm4gMSAjIFRPRE8gKGRvZXMgdGhhdCByZWxhdGUgdG8gUEFSU0VSX0xPQUREVEQpPwogICAgICAgIGVsaWYgbmFtZSA9PSBmZWF0dXJlX2V4dGVybmFsX3BlczoKICAgICAgICAgICAgcmV0dXJuIDEgIyBUT0RPIChkb2VzIHRoYXQgcmVsYXRlIHRvIFBBUlNFUl9MT0FERFREKT8KICAgICAgICBlbHNlOgogICAgICAgICAgICByYWlzZSBTQVhOb3RSZWNvZ25pemVkRXhjZXB0aW9uKCJGZWF0dXJlICclcycgbm90IHJlY29nbml6ZWQiICUgXAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hbWUpCgogICAgZGVmIHNldEZlYXR1cmUoc2VsZiwgbmFtZSwgc3RhdGUpOgogICAgICAgIGlmIHNlbGYuX19wYXJzaW5nOgogICAgICAgICAgICByYWlzZSBTQVhOb3RTdXBwb3J0ZWRFeGNlcHRpb24oIkNhbm5vdCBzZXQgZmVhdHVyZSAlcyAiIFwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJ3aGlsZSBwYXJzaW5nIiAlIG5hbWUpCiAgICAgICAgaWYgbmFtZSA9PSBmZWF0dXJlX25hbWVzcGFjZXM6CiAgICAgICAgICAgIHNlbGYuX19ucyA9IHN0YXRlCiAgICAgICAgZWxpZiBuYW1lID09IGZlYXR1cmVfbmFtZXNwYWNlX3ByZWZpeGVzOgogICAgICAgICAgICBzZWxmLl9fbnNwZnggPSBzdGF0ZQogICAgICAgIGVsaWYgbmFtZSA9PSBmZWF0dXJlX3ZhbGlkYXRpb246CiAgICAgICAgICAgIHNlbGYuX192YWxpZGF0ZSA9IHN0YXRlCiAgICAgICAgZWxpZiBuYW1lID09IGZlYXR1cmVfZXh0ZXJuYWxfZ2VzOgogICAgICAgICAgICBpZiBzdGF0ZSA9PSAwOgogICAgICAgICAgICAgICAgIyBUT0RPIChkb2VzIHRoYXQgcmVsYXRlIHRvIFBBUlNFUl9MT0FERFREKT8KICAgICAgICAgICAgICAgIHJhaXNlIFNBWE5vdFN1cHBvcnRlZEV4Y2VwdGlvbigiRmVhdHVyZSAnJXMnIG5vdCBzdXBwb3J0ZWQiICUgXAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hbWUpCiAgICAgICAgZWxpZiBuYW1lID09IGZlYXR1cmVfZXh0ZXJuYWxfcGVzOgogICAgICAgICAgICBpZiBzdGF0ZSA9PSAwOgogICAgICAgICAgICAgICAgIyBUT0RPIChkb2VzIHRoYXQgcmVsYXRlIHRvIFBBUlNFUl9MT0FERFREKT8KICAgICAgICAgICAgICAgIHJhaXNlIFNBWE5vdFN1cHBvcnRlZEV4Y2VwdGlvbigiRmVhdHVyZSAnJXMnIG5vdCBzdXBwb3J0ZWQiICUgXAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hbWUpCiAgICAgICAgZWxzZToKICAgICAgICAgICAgcmFpc2UgU0FYTm90UmVjb2duaXplZEV4Y2VwdGlvbigiRmVhdHVyZSAnJXMnIG5vdCByZWNvZ25pemVkIiAlIFwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lKQoKICAgIGRlZiBnZXRQcm9wZXJ0eShzZWxmLCBuYW1lKToKICAgICAgICBpZiBuYW1lID09IHByb3BlcnR5X2xleGljYWxfaGFuZGxlcjoKICAgICAgICAgICAgcmV0dXJuIHNlbGYuX19sZXhfaGFuZGxlcgogICAgICAgIGVsaWYgbmFtZSA9PSBwcm9wZXJ0eV9kZWNsYXJhdGlvbl9oYW5kbGVyOgogICAgICAgICAgICByZXR1cm4gc2VsZi5fX2RlY2xfaGFuZGxlcgogICAgICAgIGVsc2U6CiAgICAgICAgICAgIHJhaXNlIFNBWE5vdFJlY29nbml6ZWRFeGNlcHRpb24oIlByb3BlcnR5ICclcycgbm90IHJlY29nbml6ZWQiICUgXAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hbWUpCgogICAgZGVmIHNldFByb3BlcnR5KHNlbGYsIG5hbWUsIHZhbHVlKTogICAgIAogICAgICAgIGlmIG5hbWUgPT0gcHJvcGVydHlfbGV4aWNhbF9oYW5kbGVyOgogICAgICAgICAgICBzZWxmLl9fbGV4X2hhbmRsZXIgPSB2YWx1ZQogICAgICAgIGVsaWYgbmFtZSA9PSBwcm9wZXJ0eV9kZWNsYXJhdGlvbl9oYW5kbGVyOgogICAgICAgICAgICAjIFRPRE86IHJlbW92ZSBpZi93aGVuIGxpYnhtbDIgc3VwcG9ydHMgZHRkIGV2ZW50cwogICAgICAgICAgICByYWlzZSBTQVhOb3RTdXBwb3J0ZWRFeGNlcHRpb24oIlByb3BlcnR5ICclcycgbm90IHN1cHBvcnRlZCIgJSBcCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lKQogICAgICAgICAgICBzZWxmLl9fZGVjbF9oYW5kbGVyID0gdmFsdWUKICAgICAgICBlbHNlOgogICAgICAgICAgICByYWlzZSBTQVhOb3RSZWNvZ25pemVkRXhjZXB0aW9uKCJQcm9wZXJ0eSAnJXMnIG5vdCByZWNvZ25pemVkIiAlIFwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lKQoKZGVmIGNyZWF0ZV9wYXJzZXIoKToKICAgIHJldHVybiBMaWJYbWwyUmVhZGVyKCkKCg==