LyoKICogQ29weXJpZ2h0IChDKSAyMDA3LTIwMDggQVJNIExpbWl0ZWQKICoKICogTGljZW5zZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMCAodGhlICJMaWNlbnNlIik7CiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS4KICogWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0CiAqCiAqICAgICAgaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wCiAqCiAqIFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmUKICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gIkFTIElTIiBCQVNJUywKICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuCiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmQKICogbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuCiAqCiAqLwovKioKICogCiAqIEZpbGUgTmFtZTogIGFybVZDTTRQMl9CbG9ja01hdGNoX0ludGVnZXIuYwogKiBPcGVuTUFYIERMOiB2MS4wLjIKICogUmV2aXNpb246ICAgOTY0MQogKiBEYXRlOiAgICAgICBUaHVyc2RheSwgRmVicnVhcnkgNywgMjAwOAogKiAKICogCiAqIAogKgogKiBEZXNjcmlwdGlvbjoKICogQ29udGFpbnMgbW9kdWxlcyBmb3IgQmxvY2sgbWF0Y2hpbmcsIGEgZnVsbCBzZWFyY2ggYWxnb3JpdGhtCiAqIGlzIGltcGxlbWVudGVkCiAqIAogKi8KIAojaW5jbHVkZSAib214dHlwZXMuaCIKI2luY2x1ZGUgImFybU9NWC5oIgojaW5jbHVkZSAib214VkMuaCIKCiNpbmNsdWRlICJhcm1WQy5oIgojaW5jbHVkZSAiYXJtQ09NTS5oIgoKLyoqCiAqIEZ1bmN0aW9uOiBhcm1WQ000UDJfQmxvY2tNYXRjaF9JbnRlZ2VyCiAqCiAqIERlc2NyaXB0aW9uOgogKiBQZXJmb3JtcyBhIDE2eDE2IGJsb2NrIHNlYXJjaDsgZXN0aW1hdGVzIG1vdGlvbiB2ZWN0b3IgYW5kIGFzc29jaWF0ZWQgbWluaW11bSBTQUQuICAKICogQm90aCB0aGUgaW5wdXQgYW5kIG91dHB1dCBtb3Rpb24gdmVjdG9ycyBhcmUgcmVwcmVzZW50ZWQgdXNpbmcgaGFsZi1waXhlbCB1bml0cywgYW5kIAogKiB0aGVyZWZvcmUgYSBzaGlmdCBsZWZ0IG9yIHJpZ2h0IGJ5IDEgYml0IG1heSBiZSByZXF1aXJlZCwgcmVzcGVjdGl2ZWx5LCB0byBtYXRjaCB0aGUgCiAqIGlucHV0IG9yIG91dHB1dCBNVnMgd2l0aCBvdGhlciBmdW5jdGlvbnMgdGhhdCBlaXRoZXIgZ2VuZXJhdGUgb3V0cHV0IE1WcyBvciBleHBlY3QgCiAqIGlucHV0IE1WcyByZXByZXNlbnRlZCB1c2luZyBpbnRlZ2VyIHBpeGVsIHVuaXRzLiAKICoKICogUmVtYXJrczoKICoKICogUGFyYW1ldGVyczoKICogW2luXQlwU3JjUmVmQnVmCQlwb2ludGVyIHRvIHRoZSByZWZlcmVuY2UgWSBwbGFuZTsgcG9pbnRzIHRvIHRoZSByZWZlcmVuY2UgTUIgdGhhdCAKICogICAgICAgICAgICAgICAgICAgIGNvcnJlc3BvbmRzIHRvIHRoZSBsb2NhdGlvbiBvZiB0aGUgY3VycmVudCBtYWNyb2Jsb2NrIGluIHRoZSBjdXJyZW50IAogKiAgICAgICAgICAgICAgICAgICAgcGxhbmUuCiAqIFtpbl0JcmVmV2lkdGgJCSAgd2lkdGggb2YgdGhlIHJlZmVyZW5jZSBwbGFuZQogKiBbaW5dCXBSZWZSZWN0CQkgIHBvaW50ZXIgdG8gdGhlIHZhbGlkIHJlY3Rhbmd1bGFyIGluIHJlZmVyZW5jZSBwbGFuZS4gUmVsYXRpdmUgdG8gaW1hZ2Ugb3JpZ2luLiAKICogICAgICAgICAgICAgICAgICAgIEl0J3Mgbm90IGxpbWl0ZWQgdG8gdGhlIGltYWdlIGJvdW5kYXJ5LCBidXQgZGVwZW5kZWQgb24gdGhlIHBhZGRpbmcuIEZvciBleGFtcGxlLCAKICogICAgICAgICAgICAgICAgICAgIGlmIHlvdSBwYWQgNCBwaXhlbHMgb3V0c2lkZSB0aGUgaW1hZ2UgYm9yZGVyLCB0aGVuIHRoZSB2YWx1ZSBmb3IgbGVmdCBib3JkZXIgCiAqICAgICAgICAgICAgICAgICAgICBjYW4gYmUgLTQKICogW2luXQlwU3JjQ3VyckJ1ZgkJcG9pbnRlciB0byB0aGUgY3VycmVudCBtYWNyb2Jsb2NrIGV4dHJhY3RlZCBmcm9tIG9yaWdpbmFsIHBsYW5lIChsaW5lYXIgYXJyYXksIAogKiAgICAgICAgICAgICAgICAgICAgMjU2IGVudHJpZXMpOyBtdXN0IGJlIGFsaWduZWQgb24gYW4gOC1ieXRlIGJvdW5kYXJ5LgogKiBbaW5dIHBDdXJyUG9pbnRQb3MJcG9zaXRpb24gb2YgdGhlIGN1cnJlbnQgbWFjcm9ibG9jayBpbiB0aGUgY3VycmVudCBwbGFuZQogKiBbaW5dIHBTcmNQcmVNVgkJICBwb2ludGVyIHRvIHByZWRpY3RlZCBtb3Rpb24gdmVjdG9yOyBOVUxMIGluZGljYXRlcyBubyBwcmVkaWN0ZWQgTVYKICogW2luXSBwU3JjUHJlU0FECQlwb2ludGVyIHRvIFNBRCBhc3NvY2lhdGVkIHdpdGggdGhlIHByZWRpY3RlZCBNViAocmVmZXJlbmNlZCBieSBwU3JjUHJlTVYpCiAqIFtpbl0gc2VhcmNoUmFuZ2UJCXNlYXJjaCByYW5nZSBmb3IgMTZYMTYgaW50ZWdlciBibG9jayx0aGUgdW5pdHMgb2YgaXQgaXMgZnVsbCBwaXhlbCx0aGUgc2VhcmNoIHJhbmdlIAogKiAgICAgICAgICAgICAgICAgICAgaXMgdGhlIHNhbWUgaW4gYWxsIGRpcmVjdGlvbnMuSXQgaXMgaW4gaW5jbHVzaXZlIG9mIHRoZSBib3VuZGFyeSBhbmQgc3BlY2lmaWVkIGluIAogKiAgICAgICAgICAgICAgICAgICAgdGVybXMgb2YgaW50ZWdlciBwaXhlbCB1bml0cy4KICogW2luXSBwTUVTcGVjCQkJICB2ZW5kb3Itc3BlY2lmaWMgbW90aW9uIGVzdGltYXRpb24gc3BlY2lmaWNhdGlvbiBzdHJ1Y3R1cmU7IG11c3QgaGF2ZSBiZWVuIGFsbG9jYXRlZCAKICogICAgICAgICAgICAgICAgICAgIGFuZCB0aGVuIGluaXRpYWxpemVkIHVzaW5nIG9teFZDTTRQMl9NRUluaXQgcHJpb3IgdG8gY2FsbGluZyB0aGUgYmxvY2sgbWF0Y2hpbmcgCiAqICAgICAgICAgICAgICAgICAgICBmdW5jdGlvbi4KICogW291dF0JcERzdE1WCQkJcG9pbnRlciB0byBlc3RpbWF0ZWQgTVYKICogW291dF0JcERzdFNBRAkJCXBvaW50ZXIgdG8gbWluaW11bSBTQUQKICoKICogUmV0dXJuIFZhbHVlOgogKiBPTVhfU3RzX05vRXJyIKhDIG5vIGVycm9yLgogKiBPTVhfU3RzX0JhZEFyZ0VyciCoQyBiYWQgYXJndW1lbnRzCiAqCiAqLwoKT01YUmVzdWx0IGFybVZDTTRQMl9CbG9ja01hdGNoX0ludGVnZXIoCiAgICAgY29uc3QgT01YX1U4ICpwU3JjUmVmQnVmLAogICAgIE9NWF9JTlQgcmVmV2lkdGgsCiAgICAgY29uc3QgT01YUmVjdCAqcFJlZlJlY3QsCiAgICAgY29uc3QgT01YX1U4ICpwU3JjQ3VyckJ1ZiwKICAgICBjb25zdCBPTVhWQ000UDJDb29yZGluYXRlICpwQ3VyclBvaW50UG9zLAogICAgIGNvbnN0IE9NWFZDTW90aW9uVmVjdG9yICpwU3JjUHJlTVYsCiAgICAgY29uc3QgT01YX0lOVCAqcFNyY1ByZVNBRCwKICAgICB2b2lkICpwTUVTcGVjLAogICAgIE9NWFZDTW90aW9uVmVjdG9yICpwRHN0TVYsCiAgICAgT01YX0lOVCAqcERzdFNBRCwKICAgICBPTVhfVTggQmxvY2tTaXplCikKewoKICAgIC8qIERlZmluaXRpb25zIGFuZCBJbml0aWFsaXphdGlvbnMqLwoKICAgIE9NWF9JTlQgICAgIG91dGVyLCBpbm5lciwgY291bnQsaW5kZXg7CiAgICBPTVhfSU5UICAgICBjYW5kU0FEOwogICAgLyooMjU2KjI1NiArMSkgdGhpcyBpcyB0byBtYWtlIHRoZSBTQUQgbWF4IGluaXRpYWxseSovCiAgICBPTVhfSU5UICAgICBtaW5TQUQgPSAweDEwMDAxLCBmcm9tWCwgdG9YLCBmcm9tWSwgdG9ZOwogICAgLyogT2Zmc2V0IHRvIHRoZSByZWZlcmVuY2UgYXQgdGhlIGJlZ2luaW5nIG9mIHRoZSBib3VuZGluZyBib3ggKi8KICAgIGNvbnN0IE9NWF9VOCAgICAgICpwVGVtcFNyY1JlZkJ1ZjsKICAgIE9NWF9TMTYgICAgIHgsIHk7CiAgICBPTVhfSU5UIHNlYXJjaFJhbmdlOwogICAKICAgIC8qIEFyZ3VtZW50IGVycm9yIGNoZWNrcyAqLwogICAgYXJtUmV0QXJnRXJySWYocFNyY1JlZkJ1ZiA9PSBOVUxMLCBPTVhfU3RzX0JhZEFyZ0Vycik7CiAgICBhcm1SZXRBcmdFcnJJZihwUmVmUmVjdCA9PSBOVUxMLCBPTVhfU3RzX0JhZEFyZ0Vycik7CiAgICBhcm1SZXRBcmdFcnJJZihwU3JjQ3VyckJ1ZiA9PSBOVUxMLCBPTVhfU3RzX0JhZEFyZ0Vycik7CiAgICBhcm1SZXRBcmdFcnJJZihwQ3VyclBvaW50UG9zID09IE5VTEwsIE9NWF9TdHNfQmFkQXJnRXJyKTsKICAgIGFybVJldEFyZ0VycklmKHBNRVNwZWMgPT0gTlVMTCwgT01YX1N0c19CYWRBcmdFcnIpOwogICAgYXJtUmV0QXJnRXJySWYocERzdE1WID09IE5VTEwsIE9NWF9TdHNfQmFkQXJnRXJyKTsKICAgIGFybVJldEFyZ0VycklmKHBEc3RTQUQgPT0gTlVMTCwgT01YX1N0c19CYWRBcmdFcnIpOwogICAgICAgIAogICAgc2VhcmNoUmFuZ2UgPSAoKE9NWFZDTTRQMk1FUGFyYW1zICopcE1FU3BlYyktPnNlYXJjaFJhbmdlOwogICAgLyogQ2hlY2sgZm9yIHZhbGlkIHJlZ2lvbiAqLwogICAgZnJvbVggPSBzZWFyY2hSYW5nZTsKICAgIHRvWCAgID0gc2VhcmNoUmFuZ2U7CiAgICBmcm9tWSA9IHNlYXJjaFJhbmdlOwogICAgdG9ZICAgPSBzZWFyY2hSYW5nZTsKCiAgICBpZiAoKHBDdXJyUG9pbnRQb3MtPnggLSBzZWFyY2hSYW5nZSkgPCBwUmVmUmVjdC0+eCkKICAgIHsKICAgICAgICBmcm9tWCA9ICBwQ3VyclBvaW50UG9zLT54IC0gcFJlZlJlY3QtPng7CiAgICB9CgogICAgaWYgKChwQ3VyclBvaW50UG9zLT54ICsgQmxvY2tTaXplICsgc2VhcmNoUmFuZ2UpID4gKHBSZWZSZWN0LT54ICsgcFJlZlJlY3QtPndpZHRoKSkKICAgIHsKICAgICAgICB0b1ggICA9IHBSZWZSZWN0LT53aWR0aCAtIChwQ3VyclBvaW50UG9zLT54IC0gcFJlZlJlY3QtPngpIC0gQmxvY2tTaXplOwogICAgfQoKICAgIGlmICgocEN1cnJQb2ludFBvcy0+eSAtIHNlYXJjaFJhbmdlKSA8IHBSZWZSZWN0LT55KQogICAgewogICAgICAgIGZyb21ZID0gcEN1cnJQb2ludFBvcy0+eSAtIHBSZWZSZWN0LT55OwogICAgfQoKICAgIGlmICgocEN1cnJQb2ludFBvcy0+eSArIEJsb2NrU2l6ZSArIHNlYXJjaFJhbmdlKSA+IChwUmVmUmVjdC0+eSArIHBSZWZSZWN0LT5oZWlnaHQpKQogICAgewogICAgICAgIHRvWSAgID0gcFJlZlJlY3QtPndpZHRoIC0gKHBDdXJyUG9pbnRQb3MtPnkgLSBwUmVmUmVjdC0+eSkgLSBCbG9ja1NpemU7CiAgICB9CgogICAgcERzdE1WLT5keCA9IC1mcm9tWDsKICAgIHBEc3RNVi0+ZHkgPSAtZnJvbVk7CiAgICAvKiBMb29waW5nIG9uIHktIGF4aXMgKi8KICAgIGZvciAoeSA9IC1mcm9tWTsgeSA8PSB0b1k7IHkrKykKICAgIHsKCiAgICAgICAgLyogTG9vcGluZyBvbiB4LSBheGlzICovCiAgICAgICAgZm9yICh4ID0gLWZyb21YOyB4IDw9IHRvWDsgeCsrKQogICAgICAgIHsKICAgICAgICAgICAgLyogUG9zaXRpb25pbmcgdGhlIHBvaW50ZXIgKi8KICAgICAgICAgICAgcFRlbXBTcmNSZWZCdWYgPSBwU3JjUmVmQnVmICsgKHJlZldpZHRoICogeSkgKyB4OwoKICAgICAgICAgICAgLyogQ2FsY3VsYXRlIHRoZSBTQUQgKi8KICAgICAgICAgICAgZm9yIChvdXRlciA9IDAsIGNvdW50ID0gMCwgaW5kZXggPSAwLCBjYW5kU0FEID0gMDsKICAgICAgICAgICAgICAgICBvdXRlciA8IEJsb2NrU2l6ZTsKICAgICAgICAgICAgICAgICBvdXRlcisrLCBpbmRleCArPSByZWZXaWR0aCAtIEJsb2NrU2l6ZSkKICAgICAgICAgICAgewogICAgICAgICAgICAgICAgZm9yIChpbm5lciA9IDA7IGlubmVyIDwgQmxvY2tTaXplOyBpbm5lcisrLCBjb3VudCsrLCBpbmRleCsrKQogICAgICAgICAgICAgICAgewogICAgICAgICAgICAgICAgICAgIGNhbmRTQUQgKz0gYXJtQWJzIChwVGVtcFNyY1JlZkJ1ZltpbmRleF0gLSBwU3JjQ3VyckJ1Zltjb3VudF0pOyAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIC8qIFJlc3VsdCBjYWxjdWxhdGlvbnMgKi8KICAgICAgICAgICAgaWYgKGFybVZDTTRQMl9Db21wYXJlTVYgKHgsIHksIGNhbmRTQUQsIHBEc3RNVi0+ZHgvMiwgcERzdE1WLT5keS8yLCBtaW5TQUQpKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICAqcERzdFNBRCA9IGNhbmRTQUQ7CiAgICAgICAgICAgICAgICBtaW5TQUQgICA9IGNhbmRTQUQ7CiAgICAgICAgICAgICAgICBwRHN0TVYtPmR4ID0geCoyOwogICAgICAgICAgICAgICAgcERzdE1WLT5keSA9IHkqMjsKICAgICAgICAgICAgfQoKICAgICAgICB9IC8qIEVuZCBvZiB4LSBheGlzICovCiAgICB9IC8qIEVuZCBvZiB5LWF4aXMgKi8KCiAgICByZXR1cm4gT01YX1N0c19Ob0VycjsKCn0KCi8qIEVuZCBvZiBmaWxlICovCg==