LyoKICogQ29weXJpZ2h0IDIwMDIgTWljaGFlbCBH/G5uZXdpZwogKgogKiBUaGlzIGxpYnJhcnkgaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yCiAqIG1vZGlmeSBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWMKICogTGljZW5zZSBhcyBwdWJsaXNoZWQgYnkgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbjsgZWl0aGVyCiAqIHZlcnNpb24gMi4xIG9mIHRoZSBMaWNlbnNlLCBvciAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLgogKgogKiBUaGlzIGxpYnJhcnkgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwKICogYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YKICogTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZSBHTlUKICogTGVzc2VyIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy4KICoKICogWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpYwogKiBMaWNlbnNlIGFsb25nIHdpdGggdGhpcyBsaWJyYXJ5OyBpZiBub3QsIHdyaXRlIHRvIHRoZSBGcmVlIFNvZnR3YXJlCiAqIEZvdW5kYXRpb24sIEluYy4sIDU5IFRlbXBsZSBQbGFjZSwgU3VpdGUgMzMwLCBCb3N0b24sIE1BICAwMjExMS0xMzA3ICBVU0EKICovCgojaW5jbHVkZSA8YXNzZXJ0Lmg+CiNpbmNsdWRlIDxzdGRhcmcuaD4KCiNkZWZpbmUgQ09CSk1BQ1JPUwojZGVmaW5lIENPTV9OT19XSU5ET1dTX0gKCiNpbmNsdWRlICJ3aW5kZWYuaCIKI2luY2x1ZGUgIndpbmJhc2UuaCIKI2luY2x1ZGUgIndpbmdkaS5oIgojaW5jbHVkZSAid2ludXNlci5oIgojaW5jbHVkZSAid2lubmxzLmgiCiNpbmNsdWRlICJ3aW5lcnJvci5oIgoKI2luY2x1ZGUgIm9sZTIuaCIKI2luY2x1ZGUgInZmdy5oIgoKI2luY2x1ZGUgIndpbmUvZGVidWcuaCIKCldJTkVfREVGQVVMVF9ERUJVR19DSEFOTkVMKGF2aWZpbGUpOwoKI2luY2x1ZGUgImluaXRndWlkLmgiCiNpbmNsdWRlICJhdmlmaWxlX3ByaXZhdGUuaCIKCkhNT0RVTEUgQVZJRklMRV9oTW9kdWxlICAgPSBOVUxMOwoKQk9PTCAgICBBVklGSUxFX2JMb2NrZWQgICA9IEZBTFNFOwpVSU5UICAgIEFWSUZJTEVfdVVzZUNvdW50ID0gMDsKCnN0YXRpYyBIUkVTVUxUIFdJTkFQSSBJQ2xhc3NGYWN0b3J5X2ZuUXVlcnlJbnRlcmZhY2UoTFBDTEFTU0ZBQ1RPUlkgaWZhY2UsUkVGSUlEIHJpaWQsTFBWT0lEICpwcG9iaik7CnN0YXRpYyBVTE9ORyAgIFdJTkFQSSBJQ2xhc3NGYWN0b3J5X2ZuQWRkUmVmKExQQ0xBU1NGQUNUT1JZIGlmYWNlKTsKc3RhdGljIFVMT05HICAgV0lOQVBJIElDbGFzc0ZhY3RvcnlfZm5SZWxlYXNlKExQQ0xBU1NGQUNUT1JZIGlmYWNlKTsKc3RhdGljIEhSRVNVTFQgV0lOQVBJIElDbGFzc0ZhY3RvcnlfZm5DcmVhdGVJbnN0YW5jZShMUENMQVNTRkFDVE9SWSBpZmFjZSxMUFVOS05PV04gcE91dGVyLFJFRklJRCByaWlkLExQVk9JRCAqcHBvYmopOwpzdGF0aWMgSFJFU1VMVCBXSU5BUEkgSUNsYXNzRmFjdG9yeV9mbkxvY2tTZXJ2ZXIoTFBDTEFTU0ZBQ1RPUlkgaWZhY2UsQk9PTCBkb2xvY2spOwoKc3RhdGljIElDbGFzc0ZhY3RvcnlWdGJsIGljbGFzc2ZhY3QgPSB7CiAgSUNsYXNzRmFjdG9yeV9mblF1ZXJ5SW50ZXJmYWNlLAogIElDbGFzc0ZhY3RvcnlfZm5BZGRSZWYsCiAgSUNsYXNzRmFjdG9yeV9mblJlbGVhc2UsCiAgSUNsYXNzRmFjdG9yeV9mbkNyZWF0ZUluc3RhbmNlLAogIElDbGFzc0ZhY3RvcnlfZm5Mb2NrU2VydmVyCn07Cgp0eXBlZGVmIHN0cnVjdAp7CiAgLyogSVVua25vd24gZmllbGRzICovCiAgSUNsYXNzRmFjdG9yeVZ0YmwgKmxwVnRibDsKICBEV09SRAkgZHdSZWY7CgogIENMU0lEICBjbHNpZDsKfSBJQ2xhc3NGYWN0b3J5SW1wbDsKCnN0YXRpYyBIUkVTVUxUIEFWSUZJTEVfQ3JlYXRlQ2xhc3NGYWN0b3J5KGNvbnN0IENMU0lEICpwY2xzaWQsIGNvbnN0IElJRCAqcmlpZCwKCQkJCQkgIExQVk9JRCAqcHB2KQp7CiAgSUNsYXNzRmFjdG9yeUltcGwgKnBDbGFzc0ZhY3RvcnkgPSBOVUxMOwogIEhSRVNVTFQgICAgICAgICAgICBocjsKCiAgKnBwdiA9IE5VTEw7CgogIHBDbGFzc0ZhY3RvcnkgPSAoSUNsYXNzRmFjdG9yeUltcGwqKUxvY2FsQWxsb2MoTFBUUiwgc2l6ZW9mKCpwQ2xhc3NGYWN0b3J5KSk7CiAgaWYgKHBDbGFzc0ZhY3RvcnkgPT0gTlVMTCkKICAgIHJldHVybiBFX09VVE9GTUVNT1JZOwoKICBwQ2xhc3NGYWN0b3J5LT5scFZ0YmwgICAgPSAmaWNsYXNzZmFjdDsKICBwQ2xhc3NGYWN0b3J5LT5kd1JlZiAgICAgPSAwOwogIG1lbWNweSgmcENsYXNzRmFjdG9yeS0+Y2xzaWQsIHBjbHNpZCwgc2l6ZW9mKHBDbGFzc0ZhY3RvcnktPmNsc2lkKSk7CgogIGhyID0gSUNsYXNzRmFjdG9yeV9RdWVyeUludGVyZmFjZSgoSUNsYXNzRmFjdG9yeSopcENsYXNzRmFjdG9yeSwgcmlpZCwgcHB2KTsKICBpZiAoRkFJTEVEKGhyKSkgewogICAgTG9jYWxGcmVlKChITE9DQUwpcENsYXNzRmFjdG9yeSk7CiAgICAqcHB2ID0gTlVMTDsKICB9CgogIHJldHVybiBocjsKfQoKc3RhdGljIEhSRVNVTFQgV0lOQVBJIElDbGFzc0ZhY3RvcnlfZm5RdWVyeUludGVyZmFjZShMUENMQVNTRkFDVE9SWSBpZmFjZSwKCQkJCQkJICAgICBSRUZJSUQgcmlpZCxMUFZPSUQgKnBwb2JqKQp7CiAgVFJBQ0UoIiglcCwlcCwlcClcbiIsIGlmYWNlLCByaWlkLCBwcG9iaik7CgogIGlmICgoSXNFcXVhbEdVSUQoJklJRF9JVW5rbm93biwgcmlpZCkpIHx8CiAgICAgIChJc0VxdWFsR1VJRCgmSUlEX0lDbGFzc0ZhY3RvcnksIHJpaWQpKSkgewogICAgKnBwb2JqID0gaWZhY2U7CiAgICBJQ2xhc3NGYWN0b3J5X0FkZFJlZihpZmFjZSk7CiAgICByZXR1cm4gU19PSzsKICB9CgogIHJldHVybiBFX05PSU5URVJGQUNFOwp9CgpzdGF0aWMgVUxPTkcgV0lOQVBJIElDbGFzc0ZhY3RvcnlfZm5BZGRSZWYoTFBDTEFTU0ZBQ1RPUlkgaWZhY2UpCnsKICBJQ2xhc3NGYWN0b3J5SW1wbCAqVGhpcyA9IChJQ2xhc3NGYWN0b3J5SW1wbCAqKWlmYWNlOwoKICBUUkFDRSgiKCVwKVxuIiwgaWZhY2UpOwoKICByZXR1cm4gKysoVGhpcy0+ZHdSZWYpOwp9CgpzdGF0aWMgVUxPTkcgV0lOQVBJIElDbGFzc0ZhY3RvcnlfZm5SZWxlYXNlKExQQ0xBU1NGQUNUT1JZIGlmYWNlKQp7CiAgSUNsYXNzRmFjdG9yeUltcGwgKlRoaXMgPSAoSUNsYXNzRmFjdG9yeUltcGwgKilpZmFjZTsKCiAgVFJBQ0UoIiglcClcbiIsIGlmYWNlKTsKICBpZiAoKC0tKFRoaXMtPmR3UmVmKSkgPiAwKQogICAgcmV0dXJuIFRoaXMtPmR3UmVmOwoKICByZXR1cm4gMDsKfQoKc3RhdGljIEhSRVNVTFQgV0lOQVBJIElDbGFzc0ZhY3RvcnlfZm5DcmVhdGVJbnN0YW5jZShMUENMQVNTRkFDVE9SWSBpZmFjZSwKCQkJCQkJICAgICBMUFVOS05PV04gcE91dGVyLAoJCQkJCQkgICAgIFJFRklJRCByaWlkLExQVk9JRCAqcHBvYmopCnsKICBJQ2xhc3NGYWN0b3J5SW1wbCAqVGhpcyA9IChJQ2xhc3NGYWN0b3J5SW1wbCAqKWlmYWNlOwoKICBUUkFDRSgiKCVwLCVwLCVzLCVwKVxuIiwgaWZhY2UsIHBPdXRlciwgZGVidWdzdHJfZ3VpZChyaWlkKSwKCXBwb2JqKTsKCiAgaWYgKHBwb2JqID09IE5VTEwgfHwgcE91dGVyICE9IE5VTEwpCiAgICByZXR1cm4gRV9GQUlMOwogICpwcG9iaiA9IE5VTEw7CgogIGlmIChJc0VxdWFsR1VJRCgmQ0xTSURfQVZJRmlsZSwgJlRoaXMtPmNsc2lkKSkKICAgIHJldHVybiBBVklGSUxFX0NyZWF0ZUFWSUZpbGUocmlpZCxwcG9iaik7CiAgaWYgKElzRXF1YWxHVUlEKCZDTFNJRF9JQ01TdHJlYW0sICZUaGlzLT5jbHNpZCkpCiAgICByZXR1cm4gQVZJRklMRV9DcmVhdGVJQ01TdHJlYW0ocmlpZCxwcG9iaik7CiAgaWYgKElzRXF1YWxHVUlEKCZDTFNJRF9XQVZGaWxlLCAmVGhpcy0+Y2xzaWQpKQogICAgcmV0dXJuIEFWSUZJTEVfQ3JlYXRlV0FWRmlsZShyaWlkLHBwb2JqKTsKICBpZiAoSXNFcXVhbEdVSUQoJkNMU0lEX0FDTVN0cmVhbSwgJlRoaXMtPmNsc2lkKSkKICAgIHJldHVybiBBVklGSUxFX0NyZWF0ZUFDTVN0cmVhbShyaWlkLHBwb2JqKTsKCiAgcmV0dXJuIEVfTk9JTlRFUkZBQ0U7Cn0KCnN0YXRpYyBIUkVTVUxUIFdJTkFQSSBJQ2xhc3NGYWN0b3J5X2ZuTG9ja1NlcnZlcihMUENMQVNTRkFDVE9SWSBpZmFjZSxCT09MIGRvbG9jaykKewogIFRSQUNFKCIoJXAsJWQpXG4iLGlmYWNlLGRvbG9jayk7CgogIEFWSUZJTEVfYkxvY2tlZCA9IGRvbG9jazsKCiAgcmV0dXJuIFNfT0s7Cn0KCkxQQ1dTVFIgQVZJRklMRV9CYXNlbmFtZVcoTFBDV1NUUiBzelBhdGgpCnsKI2RlZmluZSBTTEFTSCh3KSAoKHcpID09ICcvJyB8fCAodykgPT0gJ1xcJykKCiAgTFBDV1NUUiBzekN1cjsKCiAgZm9yIChzekN1ciA9IHN6UGF0aCArIGxzdHJsZW5XKHN6UGF0aCk7CiAgICAgICBzekN1ciA+IHN6UGF0aCAmJiAhU0xBU0goKnN6Q3VyKSAmJiAqc3pDdXIgIT0gJzonOykKICAgIHN6Q3VyLS07CgogIGlmIChzekN1ciA9PSBzelBhdGgpCiAgICByZXR1cm4gc3pDdXI7CiAgZWxzZQogICAgcmV0dXJuIHN6Q3VyICsgMTsKCiN1bmRlZiBTTEFTSAp9CgovKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICoJCURsbEdldENsYXNzT2JqZWN0IChBVklGSUwzMi5AKQogKi8KSFJFU1VMVCBXSU5BUEkgQVZJRklMRV9EbGxHZXRDbGFzc09iamVjdChjb25zdCBDTFNJRCogcGNsc2lkLFJFRklJRCBwaWlkLExQVk9JRCAqcHB2KQp7CiAgVFJBQ0UoIiglcywlcywlcClcbiIsIGRlYnVnc3RyX2d1aWQocGNsc2lkKSwgZGVidWdzdHJfZ3VpZChwaWlkKSwgcHB2KTsKCiAgaWYgKHBjbHNpZCA9PSBOVUxMIHx8IHBpaWQgPT0gTlVMTCB8fCBwcHYgPT0gTlVMTCkKICAgIHJldHVybiBFX0ZBSUw7CgogIHJldHVybiBBVklGSUxFX0NyZWF0ZUNsYXNzRmFjdG9yeShwY2xzaWQscGlpZCxwcHYpOwp9CgovKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICoJCURsbENhblVubG9hZE5vdwkJKEFWSUZJTDMyLkApCiAqLwpEV09SRCBXSU5BUEkgQVZJRklMRV9EbGxDYW5VbmxvYWROb3codm9pZCkKewogIHJldHVybiAoKEFWSUZJTEVfYkxvY2tlZCB8fCBBVklGSUxFX3VVc2VDb3VudCkgPyBTX0ZBTFNFIDogU19PSyk7Cn0KCi8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgogKgkJRGxsTWFpbgkJW0FWSUZJTDMyLmluaXRdCiAqLwpCT09MIFdJTkFQSSBEbGxNYWluKEhJTlNUQU5DRSBoSW5zdERsbCwgRFdPUkQgZmR3UmVhc29uLCBMUFZPSUQgbHB2UmVzZXJ2ZWQpCnsKICBUUkFDRSgiKCVwLCVsdSwlcClcbiIsIGhJbnN0RGxsLCBmZHdSZWFzb24sIGxwdlJlc2VydmVkKTsKCiAgc3dpdGNoIChmZHdSZWFzb24pIHsKICBjYXNlIERMTF9QUk9DRVNTX0FUVEFDSDoKICAgIERpc2FibGVUaHJlYWRMaWJyYXJ5Q2FsbHMoaEluc3REbGwpOwogICAgQVZJRklMRV9oTW9kdWxlID0gKEhNT0RVTEUpaEluc3REbGw7CiAgICBicmVhazsKICBjYXNlIERMTF9QUk9DRVNTX0RFVEFDSDoKICAgIGJyZWFrOwogIH07CgogIHJldHVybiBUUlVFOwp9Cg==