LyoKICogQ29weXJpZ2h0IDIwMDIgTWljaGFlbCBH/G5uZXdpZwogKgogKiBUaGlzIGxpYnJhcnkgaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yCiAqIG1vZGlmeSBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWMKICogTGljZW5zZSBhcyBwdWJsaXNoZWQgYnkgdGhlIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbjsgZWl0aGVyCiAqIHZlcnNpb24gMi4xIG9mIHRoZSBMaWNlbnNlLCBvciAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLgogKgogKiBUaGlzIGxpYnJhcnkgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwKICogYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2YKICogTUVSQ0hBTlRBQklMSVRZIG9yIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFLiAgU2VlIHRoZSBHTlUKICogTGVzc2VyIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy4KICoKICogWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpYwogKiBMaWNlbnNlIGFsb25nIHdpdGggdGhpcyBsaWJyYXJ5OyBpZiBub3QsIHdyaXRlIHRvIHRoZSBGcmVlIFNvZnR3YXJlCiAqIEZvdW5kYXRpb24sIEluYy4sIDUxIEZyYW5rbGluIFN0LCBGaWZ0aCBGbG9vciwgQm9zdG9uLCBNQSAwMjExMC0xMzAxLCBVU0EKICovCgojaW5jbHVkZSA8c3RkYXJnLmg+CgojZGVmaW5lIENPQkpNQUNST1MKCiNpbmNsdWRlICJ3aW5kZWYuaCIKI2luY2x1ZGUgIndpbmJhc2UuaCIKI2luY2x1ZGUgIndpbmdkaS5oIgojaW5jbHVkZSAid2ludXNlci5oIgojaW5jbHVkZSAid2luZXJyb3IuaCIKCiNpbmNsdWRlICJvbGUyLmgiCiNpbmNsdWRlICJ2ZncuaCIKCiNpbmNsdWRlICJ3aW5lL2RlYnVnLmgiCgpXSU5FX0RFRkFVTFRfREVCVUdfQ0hBTk5FTChhdmlmaWxlKTsKCiNpbmNsdWRlICJpbml0Z3VpZC5oIgojaW5jbHVkZSAiYXZpZmlsZV9wcml2YXRlLmgiCgpITU9EVUxFIEFWSUZJTEVfaE1vZHVsZSAgID0gTlVMTDsKCnN0YXRpYyBCT09MICAgIEFWSUZJTEVfYkxvY2tlZDsKc3RhdGljIFVJTlQgICAgQVZJRklMRV91VXNlQ291bnQ7CgpzdGF0aWMgSFJFU1VMVCBXSU5BUEkgSUNsYXNzRmFjdG9yeV9mblF1ZXJ5SW50ZXJmYWNlKExQQ0xBU1NGQUNUT1JZIGlmYWNlLFJFRklJRCByaWlkLExQVk9JRCAqcHBvYmopOwpzdGF0aWMgVUxPTkcgICBXSU5BUEkgSUNsYXNzRmFjdG9yeV9mbkFkZFJlZihMUENMQVNTRkFDVE9SWSBpZmFjZSk7CnN0YXRpYyBVTE9ORyAgIFdJTkFQSSBJQ2xhc3NGYWN0b3J5X2ZuUmVsZWFzZShMUENMQVNTRkFDVE9SWSBpZmFjZSk7CnN0YXRpYyBIUkVTVUxUIFdJTkFQSSBJQ2xhc3NGYWN0b3J5X2ZuQ3JlYXRlSW5zdGFuY2UoTFBDTEFTU0ZBQ1RPUlkgaWZhY2UsTFBVTktOT1dOIHBPdXRlcixSRUZJSUQgcmlpZCxMUFZPSUQgKnBwb2JqKTsKc3RhdGljIEhSRVNVTFQgV0lOQVBJIElDbGFzc0ZhY3RvcnlfZm5Mb2NrU2VydmVyKExQQ0xBU1NGQUNUT1JZIGlmYWNlLEJPT0wgZG9sb2NrKTsKCnN0YXRpYyBjb25zdCBJQ2xhc3NGYWN0b3J5VnRibCBpY2xhc3NmYWN0ID0gewogIElDbGFzc0ZhY3RvcnlfZm5RdWVyeUludGVyZmFjZSwKICBJQ2xhc3NGYWN0b3J5X2ZuQWRkUmVmLAogIElDbGFzc0ZhY3RvcnlfZm5SZWxlYXNlLAogIElDbGFzc0ZhY3RvcnlfZm5DcmVhdGVJbnN0YW5jZSwKICBJQ2xhc3NGYWN0b3J5X2ZuTG9ja1NlcnZlcgp9OwoKdHlwZWRlZiBzdHJ1Y3QKewogIC8qIElVbmtub3duIGZpZWxkcyAqLwogIGNvbnN0IElDbGFzc0ZhY3RvcnlWdGJsICpscFZ0Ymw7CiAgRFdPUkQJIGR3UmVmOwoKICBDTFNJRCAgY2xzaWQ7Cn0gSUNsYXNzRmFjdG9yeUltcGw7CgpzdGF0aWMgSFJFU1VMVCBBVklGSUxFX0NyZWF0ZUNsYXNzRmFjdG9yeShjb25zdCBDTFNJRCAqcGNsc2lkLCBjb25zdCBJSUQgKnJpaWQsCgkJCQkJICBMUFZPSUQgKnBwdikKewogIElDbGFzc0ZhY3RvcnlJbXBsICpwQ2xhc3NGYWN0b3J5ID0gTlVMTDsKICBIUkVTVUxUICAgICAgICAgICAgaHI7CgogICpwcHYgPSBOVUxMOwoKICBwQ2xhc3NGYWN0b3J5ID0gSGVhcEFsbG9jKEdldFByb2Nlc3NIZWFwKCksIDAsIHNpemVvZigqcENsYXNzRmFjdG9yeSkpOwogIGlmIChwQ2xhc3NGYWN0b3J5ID09IE5VTEwpCiAgICByZXR1cm4gRV9PVVRPRk1FTU9SWTsKCiAgcENsYXNzRmFjdG9yeS0+bHBWdGJsICAgID0gJmljbGFzc2ZhY3Q7CiAgcENsYXNzRmFjdG9yeS0+ZHdSZWYgICAgID0gMDsKICBtZW1jcHkoJnBDbGFzc0ZhY3RvcnktPmNsc2lkLCBwY2xzaWQsIHNpemVvZihwQ2xhc3NGYWN0b3J5LT5jbHNpZCkpOwoKICBociA9IElDbGFzc0ZhY3RvcnlfUXVlcnlJbnRlcmZhY2UoKElDbGFzc0ZhY3RvcnkqKXBDbGFzc0ZhY3RvcnksIHJpaWQsIHBwdik7CiAgaWYgKEZBSUxFRChocikpIHsKICAgIEhlYXBGcmVlKEdldFByb2Nlc3NIZWFwKCksIDAsIHBDbGFzc0ZhY3RvcnkpOwogICAgKnBwdiA9IE5VTEw7CiAgfQoKICByZXR1cm4gaHI7Cn0KCnN0YXRpYyBIUkVTVUxUIFdJTkFQSSBJQ2xhc3NGYWN0b3J5X2ZuUXVlcnlJbnRlcmZhY2UoTFBDTEFTU0ZBQ1RPUlkgaWZhY2UsCgkJCQkJCSAgICAgUkVGSUlEIHJpaWQsTFBWT0lEICpwcG9iaikKewogIFRSQUNFKCIoJXAsJXAsJXApXG4iLCBpZmFjZSwgcmlpZCwgcHBvYmopOwoKICBpZiAoKElzRXF1YWxHVUlEKCZJSURfSVVua25vd24sIHJpaWQpKSB8fAogICAgICAoSXNFcXVhbEdVSUQoJklJRF9JQ2xhc3NGYWN0b3J5LCByaWlkKSkpIHsKICAgICpwcG9iaiA9IGlmYWNlOwogICAgSUNsYXNzRmFjdG9yeV9BZGRSZWYoaWZhY2UpOwogICAgcmV0dXJuIFNfT0s7CiAgfQoKICByZXR1cm4gRV9OT0lOVEVSRkFDRTsKfQoKc3RhdGljIFVMT05HIFdJTkFQSSBJQ2xhc3NGYWN0b3J5X2ZuQWRkUmVmKExQQ0xBU1NGQUNUT1JZIGlmYWNlKQp7CiAgSUNsYXNzRmFjdG9yeUltcGwgKlRoaXMgPSAoSUNsYXNzRmFjdG9yeUltcGwgKilpZmFjZTsKCiAgVFJBQ0UoIiglcClcbiIsIGlmYWNlKTsKCiAgcmV0dXJuICsrKFRoaXMtPmR3UmVmKTsKfQoKc3RhdGljIFVMT05HIFdJTkFQSSBJQ2xhc3NGYWN0b3J5X2ZuUmVsZWFzZShMUENMQVNTRkFDVE9SWSBpZmFjZSkKewogIElDbGFzc0ZhY3RvcnlJbXBsICpUaGlzID0gKElDbGFzc0ZhY3RvcnlJbXBsICopaWZhY2U7CgogIFRSQUNFKCIoJXApXG4iLCBpZmFjZSk7CiAgaWYgKCgtLShUaGlzLT5kd1JlZikpID4gMCkKICAgIHJldHVybiBUaGlzLT5kd1JlZjsKCiAgSGVhcEZyZWUoR2V0UHJvY2Vzc0hlYXAoKSwgMCwgVGhpcyk7CgogIHJldHVybiAwOwp9CgpzdGF0aWMgSFJFU1VMVCBXSU5BUEkgSUNsYXNzRmFjdG9yeV9mbkNyZWF0ZUluc3RhbmNlKExQQ0xBU1NGQUNUT1JZIGlmYWNlLAoJCQkJCQkgICAgIExQVU5LTk9XTiBwT3V0ZXIsCgkJCQkJCSAgICAgUkVGSUlEIHJpaWQsTFBWT0lEICpwcG9iaikKewogIElDbGFzc0ZhY3RvcnlJbXBsICpUaGlzID0gKElDbGFzc0ZhY3RvcnlJbXBsICopaWZhY2U7CgogIFRSQUNFKCIoJXAsJXAsJXMsJXApXG4iLCBpZmFjZSwgcE91dGVyLCBkZWJ1Z3N0cl9ndWlkKHJpaWQpLAoJcHBvYmopOwoKICBpZiAocHBvYmogPT0gTlVMTCB8fCBwT3V0ZXIgIT0gTlVMTCkKICAgIHJldHVybiBFX0ZBSUw7CiAgKnBwb2JqID0gTlVMTDsKCiAgaWYgKElzRXF1YWxHVUlEKCZDTFNJRF9BVklGaWxlLCAmVGhpcy0+Y2xzaWQpKQogICAgcmV0dXJuIEFWSUZJTEVfQ3JlYXRlQVZJRmlsZShyaWlkLHBwb2JqKTsKICBpZiAoSXNFcXVhbEdVSUQoJkNMU0lEX0lDTVN0cmVhbSwgJlRoaXMtPmNsc2lkKSkKICAgIHJldHVybiBBVklGSUxFX0NyZWF0ZUlDTVN0cmVhbShyaWlkLHBwb2JqKTsKICBpZiAoSXNFcXVhbEdVSUQoJkNMU0lEX1dBVkZpbGUsICZUaGlzLT5jbHNpZCkpCiAgICByZXR1cm4gQVZJRklMRV9DcmVhdGVXQVZGaWxlKHJpaWQscHBvYmopOwogIGlmIChJc0VxdWFsR1VJRCgmQ0xTSURfQUNNU3RyZWFtLCAmVGhpcy0+Y2xzaWQpKQogICAgcmV0dXJuIEFWSUZJTEVfQ3JlYXRlQUNNU3RyZWFtKHJpaWQscHBvYmopOwoKICByZXR1cm4gRV9OT0lOVEVSRkFDRTsKfQoKc3RhdGljIEhSRVNVTFQgV0lOQVBJIElDbGFzc0ZhY3RvcnlfZm5Mb2NrU2VydmVyKExQQ0xBU1NGQUNUT1JZIGlmYWNlLEJPT0wgZG9sb2NrKQp7CiAgVFJBQ0UoIiglcCwlZClcbiIsaWZhY2UsZG9sb2NrKTsKCiAgQVZJRklMRV9iTG9ja2VkID0gZG9sb2NrOwoKICByZXR1cm4gU19PSzsKfQoKTFBDV1NUUiBBVklGSUxFX0Jhc2VuYW1lVyhMUENXU1RSIHN6UGF0aCkKewojZGVmaW5lIFNMQVNIKHcpICgodykgPT0gJy8nIHx8ICh3KSA9PSAnXFwnKQoKICBMUENXU1RSIHN6Q3VyOwoKICBmb3IgKHN6Q3VyID0gc3pQYXRoICsgbHN0cmxlblcoc3pQYXRoKTsKICAgICAgIHN6Q3VyID4gc3pQYXRoICYmICFTTEFTSCgqc3pDdXIpICYmICpzekN1ciAhPSAnOic7KQogICAgc3pDdXItLTsKCiAgaWYgKHN6Q3VyID09IHN6UGF0aCkKICAgIHJldHVybiBzekN1cjsKICBlbHNlCiAgICByZXR1cm4gc3pDdXIgKyAxOwoKI3VuZGVmIFNMQVNICn0KCi8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKgogKgkJRGxsR2V0Q2xhc3NPYmplY3QgKEFWSUZJTDMyLkApCiAqLwpIUkVTVUxUIFdJTkFQSSBEbGxHZXRDbGFzc09iamVjdChSRUZDTFNJRCBwY2xzaWQsIFJFRklJRCBwaWlkLCBMUFZPSUQgKnBwdikKewogIFRSQUNFKCIoJXMsJXMsJXApXG4iLCBkZWJ1Z3N0cl9ndWlkKHBjbHNpZCksIGRlYnVnc3RyX2d1aWQocGlpZCksIHBwdik7CgogIGlmIChwY2xzaWQgPT0gTlVMTCB8fCBwaWlkID09IE5VTEwgfHwgcHB2ID09IE5VTEwpCiAgICByZXR1cm4gRV9GQUlMOwoKICByZXR1cm4gQVZJRklMRV9DcmVhdGVDbGFzc0ZhY3RvcnkocGNsc2lkLHBpaWQscHB2KTsKfQoKLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqCiAqCQlEbGxDYW5VbmxvYWROb3cJCShBVklGSUwzMi5AKQogKi8KSFJFU1VMVCBXSU5BUEkgRGxsQ2FuVW5sb2FkTm93KHZvaWQpCnsKICByZXR1cm4gKChBVklGSUxFX2JMb2NrZWQgfHwgQVZJRklMRV91VXNlQ291bnQpID8gU19GQUxTRSA6IFNfT0spOwp9CgovKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioKICoJCURsbE1haW4JCVtBVklGSUwzMi5pbml0XQogKi8KQk9PTCBXSU5BUEkgRGxsTWFpbihISU5TVEFOQ0UgaEluc3REbGwsIERXT1JEIGZkd1JlYXNvbiwgTFBWT0lEIGxwdlJlc2VydmVkKQp7CiAgVFJBQ0UoIiglcCwlZCwlcClcbiIsIGhJbnN0RGxsLCBmZHdSZWFzb24sIGxwdlJlc2VydmVkKTsKCiAgc3dpdGNoIChmZHdSZWFzb24pIHsKICBjYXNlIERMTF9QUk9DRVNTX0FUVEFDSDoKICAgIERpc2FibGVUaHJlYWRMaWJyYXJ5Q2FsbHMoaEluc3REbGwpOwogICAgQVZJRklMRV9oTW9kdWxlID0gKEhNT0RVTEUpaEluc3REbGw7CiAgICBicmVhazsKICBjYXNlIERMTF9QUk9DRVNTX0RFVEFDSDoKICAgIGJyZWFrOwogIH07CgogIHJldHVybiBUUlVFOwp9Cg==