Ly8KLy8gqSBDb3B5cmlnaHQgSGVucmlrIFJhdm4gMjAwNAovLwovLyBVc2UsIG1vZGlmaWNhdGlvbiBhbmQgZGlzdHJpYnV0aW9uIGFyZSBzdWJqZWN0IHRvIHRoZSBCb29zdCBTb2Z0d2FyZSBMaWNlbnNlLCBWZXJzaW9uIDEuMC4KLy8gKFNlZSBhY2NvbXBhbnlpbmcgZmlsZSBMSUNFTlNFXzFfMC50eHQgb3IgY29weSBhdCBodHRwOi8vd3d3LmJvb3N0Lm9yZy9MSUNFTlNFXzFfMC50eHQpCi8vCgp1c2luZyBTeXN0ZW07CnVzaW5nIFN5c3RlbS5SdW50aW1lLkludGVyb3BTZXJ2aWNlczsKdXNpbmcgU3lzdGVtLlRleHQ7CgoKbmFtZXNwYWNlIERvdFpMaWIKewogICAgI3JlZ2lvbiBDaGVja3N1bUdlbmVyYXRvckJhc2UKICAgIC8vLyA8c3VtbWFyeT4KICAgIC8vLyBJbXBsZW1lbnRzIHRoZSBjb21tb24gZnVuY3Rpb25hbGl0eSBuZWVkZWQgZm9yIGFsbCA8c2VlIGNyZWY9IkNoZWNrc3VtR2VuZXJhdG9yIi8+cwogICAgLy8vIDwvc3VtbWFyeT4KICAgIC8vLyA8ZXhhbXBsZT48L2V4YW1wbGU+CiAgICBwdWJsaWMgYWJzdHJhY3QgY2xhc3MgQ2hlY2tzdW1HZW5lcmF0b3JCYXNlIDogQ2hlY2tzdW1HZW5lcmF0b3IKICAgIHsKICAgICAgICAvLy8gPHN1bW1hcnk+CiAgICAgICAgLy8vIFRoZSB2YWx1ZSBvZiB0aGUgY3VycmVudCBjaGVja3N1bQogICAgICAgIC8vLyA8L3N1bW1hcnk+CiAgICAgICAgcHJvdGVjdGVkIHVpbnQgX2N1cnJlbnQ7CgogICAgICAgIC8vLyA8c3VtbWFyeT4KICAgICAgICAvLy8gSW5pdGlhbGl6ZXMgYSBuZXcgaW5zdGFuY2Ugb2YgdGhlIGNoZWNrc3VtIGdlbmVyYXRvciBiYXNlIC0gdGhlIGN1cnJlbnQgY2hlY2tzdW0gaXMKICAgICAgICAvLy8gc2V0IHRvIHplcm8KICAgICAgICAvLy8gPC9zdW1tYXJ5PgogICAgICAgIHB1YmxpYyBDaGVja3N1bUdlbmVyYXRvckJhc2UoKQogICAgICAgIHsKICAgICAgICAgICAgX2N1cnJlbnQgPSAwOwogICAgICAgIH0KCiAgICAgICAgLy8vIDxzdW1tYXJ5PgogICAgICAgIC8vLyBJbml0aWFsaXplcyBhIG5ldyBpbnN0YW5jZSBvZiB0aGUgY2hlY2tzdW0gZ2VuZXJhdG9yIGJhc2V3aXRoIGEgc3BlY2lmaWVkIHZhbHVlCiAgICAgICAgLy8vIDwvc3VtbWFyeT4KICAgICAgICAvLy8gPHBhcmFtIG5hbWU9ImluaXRpYWxWYWx1ZSI+VGhlIHZhbHVlIHRvIHNldCB0aGUgY3VycmVudCBjaGVja3N1bSB0bzwvcGFyYW0+CiAgICAgICAgcHVibGljIENoZWNrc3VtR2VuZXJhdG9yQmFzZSh1aW50IGluaXRpYWxWYWx1ZSkKICAgICAgICB7CiAgICAgICAgICAgIF9jdXJyZW50ID0gaW5pdGlhbFZhbHVlOwogICAgICAgIH0KCiAgICAgICAgLy8vIDxzdW1tYXJ5PgogICAgICAgIC8vLyBSZXNldHMgdGhlIGN1cnJlbnQgY2hlY2tzdW0gdG8gemVybwogICAgICAgIC8vLyA8L3N1bW1hcnk+CiAgICAgICAgcHVibGljIHZvaWQgUmVzZXQoKSB7IF9jdXJyZW50ID0gMDsgfQoKICAgICAgICAvLy8gPHN1bW1hcnk+CiAgICAgICAgLy8vIEdldHMgdGhlIGN1cnJlbnQgY2hlY2tzdW0gdmFsdWUKICAgICAgICAvLy8gPC9zdW1tYXJ5PgogICAgICAgIHB1YmxpYyB1aW50IFZhbHVlIHsgZ2V0IHsgcmV0dXJuIF9jdXJyZW50OyB9IH0KCiAgICAgICAgLy8vIDxzdW1tYXJ5PgogICAgICAgIC8vLyBVcGRhdGVzIHRoZSBjdXJyZW50IGNoZWNrc3VtIHdpdGggcGFydCBvZiBhbiBhcnJheSBvZiBieXRlcwogICAgICAgIC8vLyA8L3N1bW1hcnk+CiAgICAgICAgLy8vIDxwYXJhbSBuYW1lPSJkYXRhIj5UaGUgZGF0YSB0byB1cGRhdGUgdGhlIGNoZWNrc3VtIHdpdGg8L3BhcmFtPgogICAgICAgIC8vLyA8cGFyYW0gbmFtZT0ib2Zmc2V0Ij5XaGVyZSBpbiA8Yz5kYXRhPC9jPiB0byBzdGFydCB1cGRhdGluZzwvcGFyYW0+CiAgICAgICAgLy8vIDxwYXJhbSBuYW1lPSJjb3VudCI+VGhlIG51bWJlciBvZiBieXRlcyBmcm9tIDxjPmRhdGE8L2M+IHRvIHVzZTwvcGFyYW0+CiAgICAgICAgLy8vIDxleGNlcHRpb24gY3JlZj0iQXJndW1lbnRFeGNlcHRpb24iPlRoZSBzdW0gb2Ygb2Zmc2V0IGFuZCBjb3VudCBpcyBsYXJnZXIgdGhhbiB0aGUgbGVuZ3RoIG9mIDxjPmRhdGE8L2M+PC9leGNlcHRpb24+CiAgICAgICAgLy8vIDxleGNlcHRpb24gY3JlZj0iTnVsbFJlZmVyZW5jZUV4Y2VwdGlvbiI+PGM+ZGF0YTwvYz4gaXMgYSBudWxsIHJlZmVyZW5jZTwvZXhjZXB0aW9uPgogICAgICAgIC8vLyA8ZXhjZXB0aW9uIGNyZWY9IkFyZ3VtZW50T3V0T2ZSYW5nZUV4Y2VwdGlvbiI+T2Zmc2V0IG9yIGNvdW50IGlzIG5lZ2F0aXZlLjwvZXhjZXB0aW9uPgogICAgICAgIC8vLyA8cmVtYXJrcz5BbGwgdGhlIG90aGVyIDxjPlVwZGF0ZTwvYz4gbWV0aG9kcyBhcmUgaW1wbG1lbmV0ZWQgaW4gdGVybXMgb2YgdGhpcyBvbmUuCiAgICAgICAgLy8vIFRoaXMgaXMgdGhlcmVmb3JlIHRoZSBvbmx5IG1ldGhvZCBhIGRlcml2ZWQgY2xhc3MgaGFzIHRvIGltcGxlbWVudDwvcmVtYXJrcz4KICAgICAgICBwdWJsaWMgYWJzdHJhY3Qgdm9pZCBVcGRhdGUoYnl0ZVtdIGRhdGEsIGludCBvZmZzZXQsIGludCBjb3VudCk7CgogICAgICAgIC8vLyA8c3VtbWFyeT4KICAgICAgICAvLy8gVXBkYXRlcyB0aGUgY3VycmVudCBjaGVja3N1bSB3aXRoIGFuIGFycmF5IG9mIGJ5dGVzLgogICAgICAgIC8vLyA8L3N1bW1hcnk+CiAgICAgICAgLy8vIDxwYXJhbSBuYW1lPSJkYXRhIj5UaGUgZGF0YSB0byB1cGRhdGUgdGhlIGNoZWNrc3VtIHdpdGg8L3BhcmFtPgogICAgICAgIHB1YmxpYyB2b2lkIFVwZGF0ZShieXRlW10gZGF0YSkKICAgICAgICB7CiAgICAgICAgICAgIFVwZGF0ZShkYXRhLCAwLCBkYXRhLkxlbmd0aCk7CiAgICAgICAgfQoKICAgICAgICAvLy8gPHN1bW1hcnk+CiAgICAgICAgLy8vIFVwZGF0ZXMgdGhlIGN1cnJlbnQgY2hlY2tzdW0gd2l0aCB0aGUgZGF0YSBmcm9tIGEgc3RyaW5nCiAgICAgICAgLy8vIDwvc3VtbWFyeT4KICAgICAgICAvLy8gPHBhcmFtIG5hbWU9ImRhdGEiPlRoZSBzdHJpbmcgdG8gdXBkYXRlIHRoZSBjaGVja3N1bSB3aXRoPC9wYXJhbT4KICAgICAgICAvLy8gPHJlbWFya3M+VGhlIGNoYXJhY3RlcnMgaW4gdGhlIHN0cmluZyBhcmUgY29udmVydGVkIGJ5IHRoZSBVVEYtOCBlbmNvZGluZzwvcmVtYXJrcz4KICAgICAgICBwdWJsaWMgdm9pZCBVcGRhdGUoc3RyaW5nIGRhdGEpCiAgICAgICAgewoJCQlVcGRhdGUoRW5jb2RpbmcuVVRGOC5HZXRCeXRlcyhkYXRhKSk7CiAgICAgICAgfQoKICAgICAgICAvLy8gPHN1bW1hcnk+CiAgICAgICAgLy8vIFVwZGF0ZXMgdGhlIGN1cnJlbnQgY2hlY2tzdW0gd2l0aCB0aGUgZGF0YSBmcm9tIGEgc3RyaW5nLCB1c2luZyBhIHNwZWNpZmljIGVuY29kaW5nCiAgICAgICAgLy8vIDwvc3VtbWFyeT4KICAgICAgICAvLy8gPHBhcmFtIG5hbWU9ImRhdGEiPlRoZSBzdHJpbmcgdG8gdXBkYXRlIHRoZSBjaGVja3N1bSB3aXRoPC9wYXJhbT4KICAgICAgICAvLy8gPHBhcmFtIG5hbWU9ImVuY29kaW5nIj5UaGUgZW5jb2RpbmcgdG8gdXNlPC9wYXJhbT4KICAgICAgICBwdWJsaWMgdm9pZCBVcGRhdGUoc3RyaW5nIGRhdGEsIEVuY29kaW5nIGVuY29kaW5nKQogICAgICAgIHsKICAgICAgICAgICAgVXBkYXRlKGVuY29kaW5nLkdldEJ5dGVzKGRhdGEpKTsKICAgICAgICB9CgogICAgfQogICAgI2VuZHJlZ2lvbgoKICAgICNyZWdpb24gQ1JDMzIKICAgIC8vLyA8c3VtbWFyeT4KICAgIC8vLyBJbXBsZW1lbnRzIGEgQ1JDMzIgY2hlY2tzdW0gZ2VuZXJhdG9yCiAgICAvLy8gPC9zdW1tYXJ5PgogICAgcHVibGljIHNlYWxlZCBjbGFzcyBDUkMzMkNoZWNrc3VtIDogQ2hlY2tzdW1HZW5lcmF0b3JCYXNlCiAgICB7CiAgICAgICAgI3JlZ2lvbiBETEwgaW1wb3J0cwoKICAgICAgICBbRGxsSW1wb3J0KCJaTElCMS5kbGwiLCBDYWxsaW5nQ29udmVudGlvbj1DYWxsaW5nQ29udmVudGlvbi5DZGVjbCldCiAgICAgICAgcHJpdmF0ZSBzdGF0aWMgZXh0ZXJuIHVpbnQgY3JjMzIodWludCBjcmMsIGludCBkYXRhLCB1aW50IGxlbmd0aCk7CgogICAgICAgICNlbmRyZWdpb24KCiAgICAgICAgLy8vIDxzdW1tYXJ5PgogICAgICAgIC8vLyBJbml0aWFsaXplcyBhIG5ldyBpbnN0YW5jZSBvZiB0aGUgQ1JDMzIgY2hlY2tzdW0gZ2VuZXJhdG9yCiAgICAgICAgLy8vIDwvc3VtbWFyeT4KICAgICAgICBwdWJsaWMgQ1JDMzJDaGVja3N1bSgpIDogYmFzZSgpIHt9CgogICAgICAgIC8vLyA8c3VtbWFyeT4KICAgICAgICAvLy8gSW5pdGlhbGl6ZXMgYSBuZXcgaW5zdGFuY2Ugb2YgdGhlIENSQzMyIGNoZWNrc3VtIGdlbmVyYXRvciB3aXRoIGEgc3BlY2lmaWVkIHZhbHVlCiAgICAgICAgLy8vIDwvc3VtbWFyeT4KICAgICAgICAvLy8gPHBhcmFtIG5hbWU9ImluaXRpYWxWYWx1ZSI+VGhlIHZhbHVlIHRvIHNldCB0aGUgY3VycmVudCBjaGVja3N1bSB0bzwvcGFyYW0+CiAgICAgICAgcHVibGljIENSQzMyQ2hlY2tzdW0odWludCBpbml0aWFsVmFsdWUpIDogYmFzZShpbml0aWFsVmFsdWUpIHt9CgogICAgICAgIC8vLyA8c3VtbWFyeT4KICAgICAgICAvLy8gVXBkYXRlcyB0aGUgY3VycmVudCBjaGVja3N1bSB3aXRoIHBhcnQgb2YgYW4gYXJyYXkgb2YgYnl0ZXMKICAgICAgICAvLy8gPC9zdW1tYXJ5PgogICAgICAgIC8vLyA8cGFyYW0gbmFtZT0iZGF0YSI+VGhlIGRhdGEgdG8gdXBkYXRlIHRoZSBjaGVja3N1bSB3aXRoPC9wYXJhbT4KICAgICAgICAvLy8gPHBhcmFtIG5hbWU9Im9mZnNldCI+V2hlcmUgaW4gPGM+ZGF0YTwvYz4gdG8gc3RhcnQgdXBkYXRpbmc8L3BhcmFtPgogICAgICAgIC8vLyA8cGFyYW0gbmFtZT0iY291bnQiPlRoZSBudW1iZXIgb2YgYnl0ZXMgZnJvbSA8Yz5kYXRhPC9jPiB0byB1c2U8L3BhcmFtPgogICAgICAgIC8vLyA8ZXhjZXB0aW9uIGNyZWY9IkFyZ3VtZW50RXhjZXB0aW9uIj5UaGUgc3VtIG9mIG9mZnNldCBhbmQgY291bnQgaXMgbGFyZ2VyIHRoYW4gdGhlIGxlbmd0aCBvZiA8Yz5kYXRhPC9jPjwvZXhjZXB0aW9uPgogICAgICAgIC8vLyA8ZXhjZXB0aW9uIGNyZWY9Ik51bGxSZWZlcmVuY2VFeGNlcHRpb24iPjxjPmRhdGE8L2M+IGlzIGEgbnVsbCByZWZlcmVuY2U8L2V4Y2VwdGlvbj4KICAgICAgICAvLy8gPGV4Y2VwdGlvbiBjcmVmPSJBcmd1bWVudE91dE9mUmFuZ2VFeGNlcHRpb24iPk9mZnNldCBvciBjb3VudCBpcyBuZWdhdGl2ZS48L2V4Y2VwdGlvbj4KICAgICAgICBwdWJsaWMgb3ZlcnJpZGUgdm9pZCBVcGRhdGUoYnl0ZVtdIGRhdGEsIGludCBvZmZzZXQsIGludCBjb3VudCkKICAgICAgICB7CiAgICAgICAgICAgIGlmIChvZmZzZXQgPCAwIHx8IGNvdW50IDwgMCkgdGhyb3cgbmV3IEFyZ3VtZW50T3V0T2ZSYW5nZUV4Y2VwdGlvbigpOwogICAgICAgICAgICBpZiAoKG9mZnNldCtjb3VudCkgPiBkYXRhLkxlbmd0aCkgdGhyb3cgbmV3IEFyZ3VtZW50RXhjZXB0aW9uKCk7CiAgICAgICAgICAgIEdDSGFuZGxlIGhEYXRhID0gR0NIYW5kbGUuQWxsb2MoZGF0YSwgR0NIYW5kbGVUeXBlLlBpbm5lZCk7CiAgICAgICAgICAgIHRyeQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBfY3VycmVudCA9IGNyYzMyKF9jdXJyZW50LCBoRGF0YS5BZGRyT2ZQaW5uZWRPYmplY3QoKS5Ub0ludDMyKCkrb2Zmc2V0LCAodWludCljb3VudCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgZmluYWxseQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBoRGF0YS5GcmVlKCk7CiAgICAgICAgICAgIH0KICAgICAgICB9CgogICAgfQogICAgI2VuZHJlZ2lvbgoKICAgICNyZWdpb24gQWRsZXIKICAgIC8vLyA8c3VtbWFyeT4KICAgIC8vLyBJbXBsZW1lbnRzIGEgY2hlY2tzdW0gZ2VuZXJhdG9yIHRoYXQgY29tcHV0ZXMgdGhlIEFkbGVyIGNoZWNrc3VtIG9uIGRhdGEKICAgIC8vLyA8L3N1bW1hcnk+CiAgICBwdWJsaWMgc2VhbGVkIGNsYXNzIEFkbGVyQ2hlY2tzdW0gOiBDaGVja3N1bUdlbmVyYXRvckJhc2UKICAgIHsKICAgICAgICAjcmVnaW9uIERMTCBpbXBvcnRzCgogICAgICAgIFtEbGxJbXBvcnQoIlpMSUIxLmRsbCIsIENhbGxpbmdDb252ZW50aW9uPUNhbGxpbmdDb252ZW50aW9uLkNkZWNsKV0KICAgICAgICBwcml2YXRlIHN0YXRpYyBleHRlcm4gdWludCBhZGxlcjMyKHVpbnQgYWRsZXIsIGludCBkYXRhLCB1aW50IGxlbmd0aCk7CgogICAgICAgICNlbmRyZWdpb24KCiAgICAgICAgLy8vIDxzdW1tYXJ5PgogICAgICAgIC8vLyBJbml0aWFsaXplcyBhIG5ldyBpbnN0YW5jZSBvZiB0aGUgQWRsZXIgY2hlY2tzdW0gZ2VuZXJhdG9yCiAgICAgICAgLy8vIDwvc3VtbWFyeT4KICAgICAgICBwdWJsaWMgQWRsZXJDaGVja3N1bSgpIDogYmFzZSgpIHt9CgogICAgICAgIC8vLyA8c3VtbWFyeT4KICAgICAgICAvLy8gSW5pdGlhbGl6ZXMgYSBuZXcgaW5zdGFuY2Ugb2YgdGhlIEFkbGVyIGNoZWNrc3VtIGdlbmVyYXRvciB3aXRoIGEgc3BlY2lmaWVkIHZhbHVlCiAgICAgICAgLy8vIDwvc3VtbWFyeT4KICAgICAgICAvLy8gPHBhcmFtIG5hbWU9ImluaXRpYWxWYWx1ZSI+VGhlIHZhbHVlIHRvIHNldCB0aGUgY3VycmVudCBjaGVja3N1bSB0bzwvcGFyYW0+CiAgICAgICAgcHVibGljIEFkbGVyQ2hlY2tzdW0odWludCBpbml0aWFsVmFsdWUpIDogYmFzZShpbml0aWFsVmFsdWUpIHt9CgogICAgICAgIC8vLyA8c3VtbWFyeT4KICAgICAgICAvLy8gVXBkYXRlcyB0aGUgY3VycmVudCBjaGVja3N1bSB3aXRoIHBhcnQgb2YgYW4gYXJyYXkgb2YgYnl0ZXMKICAgICAgICAvLy8gPC9zdW1tYXJ5PgogICAgICAgIC8vLyA8cGFyYW0gbmFtZT0iZGF0YSI+VGhlIGRhdGEgdG8gdXBkYXRlIHRoZSBjaGVja3N1bSB3aXRoPC9wYXJhbT4KICAgICAgICAvLy8gPHBhcmFtIG5hbWU9Im9mZnNldCI+V2hlcmUgaW4gPGM+ZGF0YTwvYz4gdG8gc3RhcnQgdXBkYXRpbmc8L3BhcmFtPgogICAgICAgIC8vLyA8cGFyYW0gbmFtZT0iY291bnQiPlRoZSBudW1iZXIgb2YgYnl0ZXMgZnJvbSA8Yz5kYXRhPC9jPiB0byB1c2U8L3BhcmFtPgogICAgICAgIC8vLyA8ZXhjZXB0aW9uIGNyZWY9IkFyZ3VtZW50RXhjZXB0aW9uIj5UaGUgc3VtIG9mIG9mZnNldCBhbmQgY291bnQgaXMgbGFyZ2VyIHRoYW4gdGhlIGxlbmd0aCBvZiA8Yz5kYXRhPC9jPjwvZXhjZXB0aW9uPgogICAgICAgIC8vLyA8ZXhjZXB0aW9uIGNyZWY9Ik51bGxSZWZlcmVuY2VFeGNlcHRpb24iPjxjPmRhdGE8L2M+IGlzIGEgbnVsbCByZWZlcmVuY2U8L2V4Y2VwdGlvbj4KICAgICAgICAvLy8gPGV4Y2VwdGlvbiBjcmVmPSJBcmd1bWVudE91dE9mUmFuZ2VFeGNlcHRpb24iPk9mZnNldCBvciBjb3VudCBpcyBuZWdhdGl2ZS48L2V4Y2VwdGlvbj4KICAgICAgICBwdWJsaWMgb3ZlcnJpZGUgdm9pZCBVcGRhdGUoYnl0ZVtdIGRhdGEsIGludCBvZmZzZXQsIGludCBjb3VudCkKICAgICAgICB7CiAgICAgICAgICAgIGlmIChvZmZzZXQgPCAwIHx8IGNvdW50IDwgMCkgdGhyb3cgbmV3IEFyZ3VtZW50T3V0T2ZSYW5nZUV4Y2VwdGlvbigpOwogICAgICAgICAgICBpZiAoKG9mZnNldCtjb3VudCkgPiBkYXRhLkxlbmd0aCkgdGhyb3cgbmV3IEFyZ3VtZW50RXhjZXB0aW9uKCk7CiAgICAgICAgICAgIEdDSGFuZGxlIGhEYXRhID0gR0NIYW5kbGUuQWxsb2MoZGF0YSwgR0NIYW5kbGVUeXBlLlBpbm5lZCk7CiAgICAgICAgICAgIHRyeQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICBfY3VycmVudCA9IGFkbGVyMzIoX2N1cnJlbnQsIGhEYXRhLkFkZHJPZlBpbm5lZE9iamVjdCgpLlRvSW50MzIoKStvZmZzZXQsICh1aW50KWNvdW50KTsKICAgICAgICAgICAgfQogICAgICAgICAgICBmaW5hbGx5CiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIGhEYXRhLkZyZWUoKTsKICAgICAgICAgICAgfQogICAgICAgIH0KCiAgICB9CiAgICAjZW5kcmVnaW9uCgp9